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 eax

Nivelurile 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-pie

Dacă executăm a.out ar trebui să obținem flag-ul.

Mulțumesc pentru lectură!