picoCTF2019 Reverse Engineering Asm
- 2 minute de citit
- 4 exemple de cod în C
Disponibil și în English
Pe această pagină
Salut, iată soluția mea pentru provocările de reverse engineering asm din picoCTF2019. Dacă nu cunoști assembly, te rog să urmărești câteva tutoriale despre el:
asm1 – Puncte: 200
CMP: Compară primul operand sursă cu al doilea operand sursă și setează indicatorii de stare din registrul EFLAGS în funcție de rezultat. Comparația se face scăzând al doilea operand din primul și apoi setând indicatorii de stare în același mod ca instrucțiunea SUB. Când se folosește o valoare imediată ca operand, aceasta este extinsă cu semn până la lungimea primului operand.
JG: Salt scurt dacă este mai mare (ZF=0 și SF=OF)
JNE: Salt scurt dacă nu este egal (ZF=0)
asm1: <+0>: push ebp # <+1>: mov ebp,esp # <+3>: cmp DWORD PTR [ebp+0x8],0x37a # 0x345 - 0x37a = -0x35 <+10>: jg 0x512 # -0x35 este mai mare decât 0x512 pentru că a depășit domeniul. <+12>: cmp DWORD PTR [ebp+0x8],0x345 <+19>: jne 0x50a <+21>: mov eax,DWORD PTR [ebp+0x8] <+24>: add eax,0x3 <+27>: jmp 0x529 <+29>: mov eax,DWORD PTR [ebp+0x8] <+32>: sub eax,0x3 <+35>: jmp 0x529 <+37>: cmp DWORD PTR [ebp+0x8],0x5ff # 0x345 - 0x5ff = -0x2BA <+44>: jne 0x523 # -0x2BA nu este egal cu 0x523 <+46>: mov eax,DWORD PTR [ebp+0x8] <+49>: sub eax,0x3 <+52>: jmp 0x529 <+54>: mov eax,DWORD PTR [ebp+0x8] # eax = 0x348 <+57>: add eax,0x3 # eax = eax + 3 <+60>: pop ebp <+61>: ret # întoarce eaxNivelurile următoare
Nivelurile asm2, asm3 și asm4 au devenit puțin mai complexe, iar rezolvarea lor începea să pară o corvoadă; mi se făcuse capul calendar și nu mai voiam să merg pe calea manuală. Din fericire, l-am găsit pe noahc3 și acest writeup, iar cu ajutorul lor am reușit să le rezolv ușor.
Vom modifica assembly-ul și îl vom compila cu GCC. Pe Ubuntu-ul meu de 64 de biți a trebuit să instalez pachetul gcc-multilib pentru a compila executabile de 32 de biți.
Iată codul modificat pentru sarcina asm3:
.intel_syntax noprefix.global asm3asm3: push ebp mov ebp,esp xor eax,eax mov ah,BYTE PTR [ebp+0x8] shl ax,0x10 sub al,BYTE PTR [ebp+0xe] add ah,BYTE PTR [ebp+0xc] xor ax,WORD PTR [ebp+0x10] nop pop ebp ret Următorul pas este să scriem un program simplu main.c care apelează funcțiile cu argumentele necesare:
#include <stdio.h>int main(void) { printf("Hello World!"); // printf("Flag: %un", asm2(0xe,0x22)); printf("Flag: %un", asm3(0xcdc485c1,0xd6bd5e88,0xe4c1548d)); // printf("Flag: %un", asm4("picoCTF_fdb55"));}Apoi compilăm codul assembly, fișierul main.c și executabilul final:
gcc -m32 -c asm3.S -o asm3.o -fno-stack-protector -no-pie gcc -m32 -c main.c -o main.o -fno-stack-protector -no-pie gcc -m32 -o a.out main.o asm3.o -fno-stack-protector -no-pieDacă executăm a.out ar trebui să obținem flag-ul.
Mulțumesc pentru lectură!