tsune Help

Anodic Music

challenge information

Surdnlen CTF 2025: Reversing

analysis

  • main function

int __fastcall main(int argc, const char **argv, const char **envp) { const char *dialogue; // rax int i; // [rsp+Ch] [rbp-64h] void *v6; // [rsp+10h] [rbp-60h] __int64 bank; // [rsp+18h] [rbp-58h] __int64 v8[7]; // [rsp+20h] [rbp-50h] BYREF int v9; // [rsp+58h] [rbp-18h] __int16 v10; // [rsp+5Ch] [rbp-14h] unsigned __int64 v11; // [rsp+68h] [rbp-8h] v11 = __readfsqword(0x28u); memset(v8, 0, sizeof(v8)); v9 = 0; v10 = 0; v6 = malloc(0x10uLL); bank = load_bank(16LL, argv); setbuf(_bss_start, 0LL); setbuf(stdin, 0LL); for ( i = 0; i <= 61; ++i ) { dialogue = (const char *)get_dialogue(); printf("%s", dialogue); *((_BYTE *)v8 + i) = getc(stdin); getc(stdin); md5String(v8, v6); if ( (unsigned __int8)lookup_bank(v6, bank) ) { puts("There has to be some way to talk to this person, you just haven't found it yet."); return -1; } } printf("Hey it looks like you have input the right flag. Why are you still here?"); return 0; }
  • load_bank

_QWORD *load_bank() { _QWORD *result; // rax FILE *stream; // [rsp+0h] [rbp-20h] __int64 size; // [rsp+8h] [rbp-18h] void *ptr; // [rsp+10h] [rbp-10h] stream = fopen("hardcore.bnk", "rb"); fseek(stream, 0LL, 2); size = ftell(stream); rewind(stream); ptr = malloc(size); fread(ptr, size, 1uLL, stream); fclose(stream); result = malloc(0x10uLL); *result = size; result[1] = ptr; return result; }
  • get_dialogue

char *get_dialogue() { char ptr; // [rsp+Fh] [rbp-11h] BYREF FILE *stream; // [rsp+10h] [rbp-10h] unsigned __int64 v3; // [rsp+18h] [rbp-8h] v3 = __readfsqword(0x28u); stream = fopen("/dev/urandom", "rb"); fread(&ptr, 1uLL, 1uLL, stream); return (&dialogue)[ptr & 0xF]; }
  • lookup_bank

__int64 __fastcall lookup_bank(const void *a1, _QWORD *a2) { __int64 i; // [rsp+18h] [rbp-8h] for ( i = 0LL; i < *a2 / 16LL; ++i ) { if ( !memcmp(a1, (const void *)(a2[1] + 16 * i), 0x10uLL) ) return 1LL; } return 0LL; }

solution

we can brute force flag with condition if there has already exists the hash value.

if ( (unsigned __int8)lookup_bank(v6, bank) ) { puts("There has to be some way to talk to this person, you just haven't found it yet."); return -1; }

using recursive function to find flag with all candidate.

import hashlib import string with open("hardcore.bnk","rb") as fd: bnk = fd.read() charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" def hashComp(flag:str)->bool: print(flag) res = hashlib.md5(flag.encode()).digest() not in bnk return res charset = string.ascii_letters + string.digits + string.punctuation def brute_force(flag: str) -> bool: if len(flag) == 62: return True for c in charset: nFlag = flag + c if hashComp(nFlag): if brute_force(nFlag): return True return False def main(): brute_force("") if __name__ == "__main__": main()
Last modified: 24 January 2025