Documente Academic
Documente Profesional
Documente Cultură
Această serie de postări vă va arăta cum putem dezamorsa o bombă binară. Deci,
ce este o bombă binară?
O "bombă binară" este un program C executabil Linux care constă din șase
"faze". Fiecare fază se așteaptă ca elevul să introducă un anumit șir pe stdin.
Dacă elevul intră în șirul așteptat, atunci acea fază este "dezamorsată". În caz
contrar, bomba "explodează" prin imprimarea "BOOM!! ". Scopul elevilor este
de a dezamorsa cât mai multe faze."
Am găsit acest tip de bombă pe site-ul web pentru excelenta carte "Computer
Sisteme: perspectiva unui programator".
Această serie nu este destinată să fie un tutorial despre gdb special pentru că a
fost prima dată când am folosit-o.
$ ls -l total 36
-rwxr-xr-x 1 Carlos Carlos 26406 Iun 9 15:41bombă
-rw-r--r-- 1 Carlos Carlos 4069 Iun 9 15:41 bombă.c
-rw-rw-r-- 1 Carlos Carlos 49 Iun 9 15:46README
Puteți trece un fișier ca argument pentru a evita tastarea de fiecare dată intrarea corectă
pentru fazele deja dezamorsate.
În continuare, trebuie să aruncăm o privire la executabilul bombei , care este date binare,
astfel încât să nu vedem nimic interesant dacă îl deschidem folosind $EDITOR . De
aceea avem nevoie de objdump pentru a dezasambla acest executabil.
Dacă aruncăm o privire la primele câteva linii ale acestui nou fișier, vedem:
0000000000400ac0 <_init>:
400ac0: 48 83 CE 08 sub $0x8,%rsp
400ac4: E8 F3 01 00 00 Apel 400cBc <call_gmon_start>
400AC9: 48 83 C4 08 adăuga $0x8,%rsp
400ACD: C3 Retq
Așa arată un fișier ELF atunci când este dezasamblat. Să ne uităm la funcția principală
atunci:
0000000000400da0 <principal>:
http://webcache.googleusercontent.com/search?q=cache:NPuQo5CSngAJ:blog.carlosgaldino.com/2015/11/12/defusing-a-binary-bomb-with-gdb-part-1.html+&... 2/7
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 1 · carlosgaldino
400dd6: 75 41 JNE 400e19 <principal+0x79>
400dd8: 48 8b 4b 08 MOV 0x8(%rbx),%rcx
400DDC: 48 8b 13 .mov (%rbx),%rdx
400DDF: să fie B6 22 40 00 .mov $0x4022b6,%esi
400de4: BF 01 00 00 00 .mov $0x1,%EDI
400de9: E8 12 fe ff ff Apel 400c00 <__printf_chk@plt>
400dee: BF 08 00 00 00 .mov $0x8,%EDI
400df3: E8 28 FE ff ff Apel 400C20 <exit@plt>
400df8: 48 8b 16 .mov (%rsi),%rdx
400dfb: BE D3 22 40 00 .mov $0x4022d3,%esi
400E00: BF 01 00 00 00 .mov $0x1,%EDI
400E05: b8 00 00 00 00 .mov $0x0,%eax
400E0a: E8 F1 FD FF FF Apel 400c00 <__printf_chk@plt>
400e0f: BF 08 00 00 00 .mov $0x8,%EDI
400E14: E8 07 fe ff ff Apel 400C20 <exit@plt>
400E19: E8 84 05 00 00 Apel 4013a2 <initialize_bomb>
400E1e: BF 38 23 40 00 .mov $0x402338,%EDI
400E23: E8 E8 FC FF FF Apel 400B10 <puts@plt>
400E28: BF 78 23 40 00 .mov $0x402378,%EDI
400E2d: E8 de FC FF FF Apel 400B10 <puts@plt>
400E32: E8 67 06 00 00 Apel 40149e <read_line>
400E37: 48 89 c7 .mov %rax,%CDI
400E3a: E8 A1 00 00 00 Apel 400ee0 <phase_1>
400e3f: E8 80 07 00 00 Apel 4015c4 <phase_defused>
Primele câteva linii din funcția principală corespund codului C care verifică dacă am
transmis sau nu un fișier ca argument programului. Sărind peste aceste rânduri,
începem să vedem partea distractivă:
http://webcache.googleusercontent.com/search?q=cache:NPuQo5CSngAJ:blog.carlosgaldino.com/2015/11/12/defusing-a-binary-bomb-with-gdb-part-1.html+&... 3/7
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 1 · carlosgaldino
Această linie spune că funcția initialize_bomb ar trebui apelată. Linia de corelare din
fișierul C este următoarea:
/* Faceți tot felul de lucruri secrete care fac bomba mai greu de dezamorsat.
*/
initialize_bomb();
00000000004013a2 <initialize_bomb>:
4013A2: 48 83 Ce 08 sub $0x8,%rsp
4013A6: fi A0 12 40 00 .mov $0x4012a0,%esi
4013ab: Bf 02 00 00 00 .mov $0x2,%EDI
4013b0: E8 .db F7 ff ff Apel 400B90 <signal@plt>
4013b5: 48 83 C4 08 adăuga $0x8,%rsp
4013B9: C3 Retq
/*Hmm... Șase faze trebuie să fie mai sigure decât o singură fază! */
intrare = read_line(); /* Obțineți informații */
phase_1(intrare); /* Rulați faza */
Așa că tipăresc mesajele și citesc intrarea. Apoi este timpul să dezamorsăm prima fază.
0000000000400ee0 <phase_1>:
400ee0: 48 83 CE 08 sub $0x8,%rsp
400EE4: să fie 00 24 40 00 .mov $0x402400,%esi
400EE9: E8 4A 04 00 00 Apel 401338 <strings_not_equal>
http://webcache.googleusercontent.com/search?q=cache:NPuQo5CSngAJ:blog.carlosgaldino.com/2015/11/12/defusing-a-binary-bomb-with-gdb-part-1.html+&... 4/7
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 1 · carlosgaldino
400eee: 85 c0 testa %EAX,%EAX
400ef0: 74 05 Je 400ef7 <phase_1+0x17>
400ef2: E8 43 05 00 00 Apel 40143a <explode_bomb>
400ef7: 48 83 c4 08 adăuga $0x8,%rsp
400EFB: C3 Retq
Observați pe 0x400ee4 că valoarea 0x402400 este copiată în registrul esi . Registrul esi
este de obicei folosit ca registru pentru al doilea argument al unei funcții care va fi
apelat mai târziu. În cazul nostru, o astfel de funcție este apelată imediat după
instrucțiunea mov . Ați putea întreba atunci: unde este primul argument? Primul
argument este de obicei plasat in registrul edi , care in acest caz va fi sirul pe care l-am
furnizat ca intrare. Dacă aruncați o privire la funcția principală , veți vedea:
Valoarea returnată (stocată în rax) a funcției read_line a fost plasată în registrul rdi (
edi este un registru pe 32 de biți și rdi este registrul echivalent pe 64 de biți) și va fi
utilizată ca prim argument pentru funcția care va fi apelată în continuare, care în
acest caz este phase_1 . Și exact asta face codul C:
/*Hmm... Șase faze trebuie să fie mai sigure decât o singură fază! */ intrare = read_line(); /* Obțineți
informații */
phase_1(intrare); /* Rulați faza */
Ok, înapoi la funcția phase_1 . Acum știm care sunt argumentele date strings_not_equal
și după executarea unei astfel de funcții există un test pentru a verifica rezultatul:
http://webcache.googleusercontent.com/search?q=cache:NPuQo5CSngAJ:blog.carlosgaldino.com/2015/11/12/defusing-a-binary-bomb-with-gdb-part-1.html+&... 5/7
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 1 · carlosgaldino
Instrucțiunea de testare va efectua o operație AND la nivel de biți între operanzii săi
și va seta steagurile corespunzătoare pe steagurile electronice ale registrului .
Instrucțiunea je este o instrucțiune de salt condiționată care sare la locația specificată
numai dacă comparația anterioară a setat ZF (Zero Flag) la 1 în registrul eflags .
Ok, acum știm că prima fază ne cere să furnizăm un șir pe care nu îl cunoaștem. Cum
vom descoperi care șir este acesta? Trebuie să începem să executăm programul. Dar,
în acest caz, în loc să executați așa cum faceți de obicei cu alte programe, îl vom rula
cu gdb . GDB ne va ajuta să inspectăm valorile și să aflăm ce este acest șir misterios.
$ GDB bombă
Linia de mai sus începe gdb cu programul bombei atașat la acesta, astfel încât să
putem executa bomba și să inspectăm valorile, să setăm puncte de întrerupere etc. În
acest caz, am făcut deja cea mai mare parte a muncii examinând doar codul de
asamblare și
http://webcache.googleusercontent.com/search?q=cache:NPuQo5CSngAJ:blog.carlosgaldino.com/2015/11/12/defusing-a-binary-bomb-with-gdb-part-1.html+&... 6/7
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 1 · carlosgaldino
Știm că șirul misterios se află la adresa 0x402400 (când a fost încărcat pe Register ESI
la adresa 0x400ee4 ). Pentru a vedea care este valoarea acesteia, putem cere pur și
simplu gdb să tipărească valoarea la adresa dorită și să o trateze ca secvență de
caractere :
(GDPR) Rulare
Program de pornire: /home/carlos/Downloads/bomb/bomb
Bine ați venit la mica mea bombă diabolică. Ai 6 faze cu care să te arunci în aer. O zi bună!
http://webcache.googleusercontent.com/search?q=cache:NPuQo5CSngAJ:blog.carlosgaldino.com/2015/11/12/defusing-a-binary-bomb-with-gdb-part-1.html+&... 7/7
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 2 · carlosgaldino
Acest post face parte dintr-o serie în care vă arăt cum să dezamorsați o bombă
binară citind codul de asamblare și folosind gdb . S-ar putea să doriți să citiți
prima parte dacă nu ați făcut-o încă.
După cum putem vedea ( cel 0x400e53 ) pune contribuția noastră în registrul CDI
pentru a fi folosită ca prim argument pentru a phase_2 care va fi apelat de următoarea
instrucțiune. La fel cum v-ați imagina că codul C real face:
http://webcache.googleusercontent.com/search?q=cache:0AQyhw4TGq4J:blog.carlosgaldino.com/2015/11/19/defusing-a-binary-bomb-with-gdb-part-2.html+&... 1/6
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 2 · carlosgaldino
0000000000400EFC <phase_2>:
400EFC 55 împinge %rbp
400EFD 53 împinge %rbx
400efe 48 83 Ce 28 sub $0x28,%rsp
400F02 48 89 E6 .mov %rsp,%rsi
400F05 E8 52 05 00 00 Apel 40145c <read_six_numbers>
400F0A 83 3c 24 01 CMPL $0x1,(%rsp)
400F0E 74 20 Je 400F30 <phase_2+0x34>
400F10 E8 25 05 00 00 Apel 40143a <explode_bomb>
400F15 Eb 19 JMP 400F30 <phase_2+0x34>
400F17 8b 43 Fc .mov -0x4(%RBX),%EAX
400F1A 01 c0 adăuga %EAX,%EAX
400F1C 39 03 CMP %eax,(%rbx)
400F1E 74 05 Je 400F25 <phase_2+0x29>
400F20 E8 15 05 00 00 Apel 40143a <explode_bomb>
400F25 48 83 C3 04 adăuga $0x4,%rbx
400F29 48 39 Eb CMP %rbp,%rbx
400F2C 75 E9 JNE 400F17 <phase_2+0x1b>
400F2E Eb 0c JMP 400F3C <phase_2+0x40>
400F30 48 8D 5c 24 04 pășune 0x4(%rsp),%rbx
400F35 48 8D 6c 24 18 pășune 0x18(%rsp),%rbp
400F3A Eb .db JMP 400F17 <phase_2+0x1b>
400F3C 48 83 C4 28 adăuga $0x28,%rsp
400F40 5b pop %rbx
400F41 5D pop %rbp
400F42 C3 Retq
Încă de la început putem vedea că această fază se așteaptă să introducem șase numere:
000000000040145c <read_six_numbers>:
40145C: 48 83 Ce 18 sub $0x18,%rsp
401460: 48 89 F2 .mov %rsi,%rdx
401463: 48 8D 4e 04 pășune 0x4(%rsi),%rcx
401467: 48 8D 46 14 pășune 0x14(%rsi),%rax
40146B: 48 89 44 24 08 .mov %rax,0x8(%rsp)
401470: 48 8D 46 10 pășune 0x10(%rsi),%rax
401474: 48 89 04 24 .mov %rax,(%rsp)
http://webcache.googleusercontent.com/search?q=cache:0AQyhw4TGq4J:blog.carlosgaldino.com/2015/11/19/defusing-a-binary-bomb-with-gdb-part-2.html+&... 2/6
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 2 · carlosgaldino
#include <stdio.h>
Familia de funcții scanf() scanează intrarea conform formatului descris mai jos.
Acest format poate conține specificații privind conversiile; Rezultatele unor astfel
de conversii, dacă există, sunt stocate în locațiile indicate de argumentele
indicatorului care urmează formatul . Fiecare argument indicator trebuie să fie
de un tip adecvat pentru valoarea returnată de specificația de conversie
corespunzătoare.
Urmând aceeași idee pe care am folosit-o în faza 1, putem confirma că această funcție
face exact ceea ce sugerează numele său. Pe 0x401480 ceva este stocat la esi pentru a fi
folosit ca al doilea argument pentru sscanf , care, așa cum se vede mai sus, este
formatul așteptat pentru intrarea noastră.
read_six_numbers apoi verifică dacă am tastat cel puțin șase numere, dacă am făcut-o se
întoarce, altfel explodează bomba.
http://webcache.googleusercontent.com/search?q=cache:0AQyhw4TGq4J:blog.carlosgaldino.com/2015/11/19/defusing-a-binary-bomb-with-gdb-part-2.html+&... 3/6
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 2 · carlosgaldino
400F30: 48 8d 5c 24 04 0x4(%rsp),%rbx
400F35: 48 8d 6c 24 18 lea lea 0x18(%rsp),%rbp
400F3A: EB DB JMP 400F17 <phase_2+0x1b>
Pe 0x400f30 adresa următorului număr este stocată pe rbx, iar pe 0x400f35 rbp primește
adresa imediat după adresa ultimului număr analizat de sscanf pe read_six_numbers .
(GDPR) p $rsp+0x18
$2 = (vid *) 0x7fffffffddd8
(GDPR) p $rsp
$3 = (vid *) 0x7fffffffddc0
Având în vedere doar octetul de ordin scăzut: 0xd8 - 0xc0 = 0x18 . Care este zecimal 24 .
Fiecare int are patru octeți, astfel încât structura memoriei arată ca imaginea de mai jos,
ceea ce explică de ce rbp deține adresa după al șaselea număr:
http://webcache.googleusercontent.com/search?q=cache:0AQyhw4TGq4J:blog.carlosgaldino.com/2015/11/19/defusing-a-binary-bomb-with-gdb-part-2.html+&... 4/6
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 2 · carlosgaldino
Andoc
p 0kco a Oxc? Or.cc OkaH
Lk x,
HG + OLVE OCTEȚI
x xni Xs
AE: Ok'FFFFFFFDD
<6
http://webcache.googleusercontent.com/search?q=cache:0AQyhw4TGq4J:blog.carlosgaldino.com/2015/11/19/defusing-a-binary-bomb-with-gdb-part-2.html+&... 5/6
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 2 · carlosgaldino
Bine, acum avem o idee despre care ar trebui să fie următoarele cinci numere.
Acestea trebuie să fie dublul numărului anterior. Dacă începem de la 1 , următorul
este 2 , următorul este 4 și așa mai departe. S-ar putea să sune un clopoțel, nu-i
așa? Contribuția noastră trebuie să fie primele șase puteri din 2 :
• 20 = 1
• 21 = 2
• 22 = 4
• 23 = 8
• 24 = 16
• 25 = 32
http://webcache.googleusercontent.com/search?q=cache:0AQyhw4TGq4J:blog.carlosgaldino.com/2015/11/19/defusing-a-binary-bomb-with-gdb-part-2.html+&... 6/6
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 3 · carlosgaldino
Acest post face parte dintr-o serie în care vă arăt cum să dezamorsați o bombă
binară citind codul de asamblare și folosind gdb . S-ar putea să doriți să citiți
celelalte părți dacă nu ați făcut-o încă.
Urmând procesul obișnuit, după dezamorsarea celei de-a doua faze am fost
provocați să o dezamorsăm pe a treia:
Bine ați venit la mica mea bombă diabolică. Ai 6 faze cu care să te arunci în aer. O zi bună!
Relațiile de frontieră cu Canada nu au fost niciodată mai bune.
Faza 1 dezamorsată. Ce zici de următorul?
1 2 4 8 16 32
Acesta este numărul 2. Continuă!
0000000000400f43 <phase_3>:
400F43: 4883 Ce 18 sub $0x18,%rsp
400F47: 48 8D 4c 24 0C pășune 0xc(%rsp),%rcx
400F4C: 48 8D 54 24 08 pășune 0x8(%rsp),%rdx
400F51: fi cf 25 40 00 .mov $0x4025cf,%esi
400F56: b8 00 00 00 00 .mov $0x0,%eax
http://webcache.googleusercontent.com/search?q=cache:T7QwiqsqtVEJ:blog.carlosgaldino.com/2015/14/03/dezamorsarea-unei-bombe-binare-cu-gdb-part-
3.html+&cd... 6/6
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 3 · carlosgaldino
400F5B E8 90 FC FF FF Apel 400bf0 <__isoc99_sscanf@pl
t>
400F60 83 f8 01 CMP $0x1,%eax
400F63 7f 05 Jg 400F6A <phase_3+0x27>
400F65 E8 D0 04 00 00 Apel 40143a <explode_bomb>
400F6A 83 7c 24 08 07 CMPL $0x7,0x8(%RSP)
400F6F 77 3c Ja 400fad <phase_3+0x6a>
400F71 8b 44 24 08 .mov 0x8(%rsp),%eax
400F75 ff 24 C5 70 24 40 00 jmpq *0x402470(,%rax,8)
400F7C B8 CF 00 00 00 .mov $0xcf,%eax
400F81 EB 3b JMP 400fbe <phase_3+0x7b>
400F83 B8 C3 02 00 00 .mov $0x2c3,%eax
400F88 EB 34 JMP 400fbe <phase_3+0x7b>
400F8A B8 00 01 00 00 .mov $0x100,%eax
400F8F EB 2d JMP 400fbe <phase_3+0x7b>
400F91 B8 85 01 00 00 .mov $0x185,%eax
400F96 EB 26 JMP 400fbe <phase_3+0x7b>
400F98 B8 CE 00 00 00 .mov $0xce,%eax
400F9D EB 1F JMP 400fbe <phase_3+0x7b>
400F9F B8 AA 02 00 00 .mov $0x2aa,%eax
400fa4 EB 18 JMP 400fbe <phase_3+0x7b>
400FA6 B8 47 01 00 00 .mov $0x147,%eax
400fab EB 11 JMP 400fbe <phase_3+0x7b>
400mod E8 88 04 00 00 Apel 40143a <explode_bomb>
400fb2 B8 00 00 00 00 .mov $0x0,%eax
400fb7 EB 05 JMP 400fbe <phase_3+0x7b>
400FB9 B8 37 01 00 00 .mov $0x137,%eax
400fbe 3b 44 24 0C CMP 0xc(%rsp),%eax
400FC2 74 05 Je 400fc9 <phase_3+0x86>
400fc4 E8 71 04 00 00 Apel 40143a <explode_bomb>
400FC9 48 83 C4 18 adăuga $0x18,%rsp
400FCD C3 Retq
Dacă nu vă amintiți din faza anterioară, sscanf este o funcție care scanează intrarea
în funcție de un format care îi este dat ca argument. Un astfel de format trebuie să
fie ceea ce este stocat pe esi .
http://webcache.googleusercontent.com/search?q=cache:T7QwiqsqtVEJ:blog.carlosgaldino.com/2015/15/03/dezamorsarea-unei-bombe-binare-cu-gdb-part-
3.html+&cd... 6/6
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 3 · carlosgaldino
S-ar putea să vă întrebați cum a obținut sscanf primul său argument, care este șirul
folosit ca sursă pentru scanarea valorilor dorite. După cum am explicat în postările
anterioare, primul argument pentru funcții este de obicei plasat pe registrul rdi și
orice instrucțiune poate interacționa cu orice registru, în același mod în care ați
interacționa cu o variabilă globală într-un program. Dacă vă uitați la 0x400e6f în
funcția principală , șirul pe care îl introducem ca intrare pentru phase_3 este copiat
în rdi pentru a fi apoi folosit ca prim argument pentru sscanf :
Prima instrucțiune de mai sus va copia primul număr întreg în eax și apoi pe a
doua instrucțiune va sări într-o locație bazată pe acest întreg. Să presupunem că
am introdus 0 ca primul nostru întreg. În acest caz, programul ar sări la locația
http://webcache.googleusercontent.com/search?q=cache:T7QwiqsqtVEJ:blog.carlosgaldino.com/2015/16/03/dezamorsarea-unei-bombe-binare-cu-gdb-part-
3.html+&cd... 6/6
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 3 · carlosgaldino
*(%rax * 8 + 0x402470)
Aceasta stochează 0xcf (zecimal 207) pe eax și apoi sare la 0x400fbe care face
următoarele:
0 207
La jumătatea drumului!
Deci asta este?! Destul de simplu, nu? Dar cum rămâne cu toate celelalte
instrucțiuni de peste 400fbe ? Care este scopul lor?
http://webcache.googleusercontent.com/search?q=cache:T7QwiqsqtVEJ:blog.carlosgaldino.com/2015/17/03/dezamorsarea-unei-bombe-binare-cu-gdb-part-
3.html+&cd... 6/6
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 3 · carlosgaldino
http://webcache.googleusercontent.com/search?q=cache:T7QwiqsqtVEJ:blog.carlosgaldino.com/2015/18/03/dezamorsarea-unei-bombe-binare-cu-gdb-part-
3.html+&cd... 6/6
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 3 · carlosgaldino
Note
http://webcache.googleusercontent.com/search?q=cache:T7QwiqsqtVEJ:blog.carlosgaldino.com/2015/12/03/dezamorsarea-unei-bombe-binare-cu-gdb-part-
3.html+&cd... 6/6
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 4 · carlosgaldino
Acest post face parte dintr-o serie în care vă arăt cum să dezamorsați o bombă
binară citind codul de asamblare și folosind gdb . S-ar putea să doriți să citiți
prima parte dacă nu ați făcut-o încă.
000000000040100c <phase_4>:
40100C: 48 83 CE 18
401010: 48 8d 4c 24 0c sub lea $0x18,%rsp
401015: 48 8d 54 24 08 BE CF 25 lea 0xc(%rsp),%rcx
40101a: 40 00 B8 00 00 00 00 mov 0x8(%rsp),%rdx $0x4025cf,%esi
40101F: mov $0x0,%eax
401024:
E8 C7 FB FF Ff callq 400bf0 <__isoc99_sscanf@pl
t>
401029: 83 F8 02 CMP $0x2,%eax
40102C: 75 07 JNE 401035 <phase_4+0x29>
40102e: 83 7c 24 08 0e CMPL $0xe,0x8(%rsp)
401033: 76 05 JBE 40103A <phase_4+0x2e>
401035: E8 00 04 00 00 Apel 40143a <explode_bomb>
40103a: Ba 0e 00 00 00 .mov $0xe,%EDX
40103F: fi 00 00 00 00 .mov $0x0,%esi
401044: 8b 7c 24 08 .mov 0x8(%rsp),%edi
401048: E8 81 ff ff Ff Apel 400fce <func4>
40104D: 85 c0 testa %EAX,%EAX
40104F: 75 07 JNE 401058 <phase_4+0x4c>
401051: 83 7c 24 0C 00 CMPL $0x0,0xc(%rsp)
401056: 74 05 Je 40105d <phase_4+0x51>
401058: E8 Dd 03 00 00 Apel 40143a <explode_bomb>
40105D: 48 83 C4 18 adăuga $0x18,%rsp
401061: C3 Retq
Exact așa cum s-a întâmplat în faza 3 , putem vedea că această fază așteaptă două
http://webcache.googleusercontent.com/search?q=cache:POrmVxSy8kgJ:blog.carlosgaldino.com/2016/04/25/defusing-a-binary-bomb-with-gdb-part-4.html+&c... 1/7
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 4 · carlosgaldino
numere întregi ca intrare. Pe 0x40101a același format folosit înainte este stocat pe
esi , care este apoi utilizat de sscanf pe 0x401024 .
Deci, ce numere exacte ar trebui să introducem? Trebuie să fie un număr mai mic
de 15:
CMPL compară 0xe care este 14 cu primul întreg1 pe care l-am introdus pentru
această fază. Apoi jbe ("salt sub sau egal") va sări peste explozia bombei dacă
valoarea este mai mică sau egală cu 14.
EDI este de obicei folosit ca registru pentru a ține primul argument, ESI deține al
doilea și EDX deține al treilea argument. Primul argument este primul număr pe
care l-am furnizat, al doilea și al treilea sunt 0 și 14 , respectiv.
http://webcache.googleusercontent.com/search?q=cache:POrmVxSy8kgJ:blog.carlosgaldino.com/2016/04/25/defusing-a-binary-bomb-with-gdb-part-4.html+&c... 2/7
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 4 · carlosgaldino
0000000000400fce
400fce: <func4>:
48 83 CE 08 sub $0x8,%rsp
400fd2: 89 d0 .mov %edx,%eax
400fd4: 29 f0 sub %ESI,%EAX
400fd6: 89 C1 .mov %eax,%ecx
400FD8: C1 E9 1f Shr $0x1f,%ecx
400FDB: 01 c8 adăuga %ecx,%eax
400fdd: d1 F8 Sar %eax
400FDF: 8D 0c 30 pășune (%rax,%rsi,1),%ecx
400FE2: 39 F9 CMP %EDI,%ECX
400FE4: 7e 0c JLE 400ff2 <func4+0x24>
400fe6: 8D 51 Ff pășune -0x1(%rcx),%edx
400fe9: E8 E0 ff ff ff Apel 400fce <func4>
400fee: 01 c0 adăuga %EAX,%EAX
400ff0: Eb 15 JMP 401007 <func4+0x39>
400ff2: b8 00 00 00 00 .mov $0x0,%eax
400ff7: 39 F9 CMP %EDI,%ECX
400ff9: 7D 0c JGE 401007 <func4+0x39>
400 și urm: 8D 71 01 pășune 0x1(%rcx),%esi
400ffe: E8 Cb ff ff ff Apel 400fce <func4>
401003: 8D 44 00 01 pășune 0x1(%rax,%rax,1),%eax
401007: 48 83 C4 08 adăuga $0x8,%rsp
40100b: C3 Retq
func4(a, b, y - 1);
După ce îl apelați, puteți vedea că 0x400fee va dubla rezultatul acelei invocații
"interioare" ( eax deține valoarea returnată din acea execuție) și apoi veți sări la
0x401007 care curăță cadrul stivei pentru această invocare. Deci rezultatul acestui
http://webcache.googleusercontent.com/search?q=cache:POrmVxSy8kgJ:blog.carlosgaldino.com/2016/04/25/defusing-a-binary-bomb-with-gdb-part-4.html+&c... 3/7
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 4 · carlosgaldino
func4(a, y + 1, c);
După revenirea de la acest apel recursiv, valoarea returnată este setată pe 0x401003
utilizând rezultatul apelului recursiv, astfel încât rezultatul este de fapt:
returnează 2 * func4(a, y + 1, c) + 1;
Cu tot acest context, putem încerca acum să ghicim ce se întâmplă exact cu această
funcție:
dacă (y <= a) {
dacă (y >= a) { returnează 0;
} altceva {
returnează 2 * func4(a, y + 1, c) + 1;
}
} altceva {
returnare 2 * func4(a, b, y - 1);
func4(1, 0, 6) { int x = 6 - 0;
int y = 6 >> 31; x = 6 + 0;
x = 6 >> 1;
y = 3 + 0;
}
Execuția va fi:
func4(1, 0, 2) { int x = 2 - 0;
De data aceasta y == 1 deci atât dacă ramurile vor fi luate, cât și 0 vor fi returnate
din această invocație recursivă. Amintiți-vă că am invocat această funcție de două
ori, astfel încât rezultatul final va fi:
Această linie și linia de mai jos testează dacă rezultatul acelei invocări func4 a
returnat sau nu 0 , dacă a făcut-o prima noastră intrare este corectă și execuția
continuă la 0x401051 . Această instrucțiune verifică pur și simplu dacă a doua
intrare este 0 și dacă este funcția returnează și faza 4 este dezamorsată:
10
Deci l-ai luat pe acela. Încercați-l pe acesta.
Un alt lucru interesant despre această fază este modul în care compilatorul
gestionează rezultatele apelurilor recursive. Deoarece eax este un registru,
rezultatele fiecărei invocări recursive vor fi disponibile cadrului stivei care a
invocat-o și apoi poate fi pur și simplu returnată fără a salva rezultatul în alt loc.
De asemenea, vedeți că după apelarea din nou a func4 , nu există nimic care să
gestioneze variabilele locale x și y , motiv pentru care acestea sunt stocate și în
registre în loc să fie salvate în interiorul fiecărui cadru de stivă.
http://webcache.googleusercontent.com/search?q=cache:POrmVxSy8kgJ:blog.carlosgaldino.com/2016/04/25/defusing-a-binary-bomb-with-gdb-part-4.html+&c... 6/7
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 4 · carlosgaldino
Note
http://webcache.googleusercontent.com/search?q=cache:POrmVxSy8kgJ:blog.carlosgaldino.com/2016/04/25/defusing-a-binary-bomb-with-gdb-part-4.html+&c... 7/7
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 5 · carlosgaldino
Acest post face parte dintr-o serie în care vă arăt cum să dezamorsați o bombă
binară citind codul de asamblare și folosind gdb . S-ar putea să doriți să citiți
prima parte dacă nu ați făcut-o încă.
După dezamorsarea celei de-a patra faze , programul continuă cu faza următoare:
0000000000401062 <phase_5>:
401062: 53 împinge %rbx
401063: 48 83 CE 20 sub $0x20,%rsp
401067: 48 89 FB .mov %rdi,%rbx
40106a: 64 48 8b 04 25 28 00 .mov %FS:0x28,%RAX
401071: 00 00
401073: 48 89 44 24 18 .mov %rax,0x18(%rsp)
401078: 31 c0 Xor %EAX,%EAX
40107a: E8 9C 02 00 00 Apel 40131b <string_length>
40107F: 83 f8 06 CMP $0x6,%eax
401082: 74 4e Je 4010d2 <phase_5+0x70>
401084: E8 B1 03 00 00 Apel 40143a <explode_bomb>
401089: EB 47 JMP 4010d2 <phase_5+0x70>
40108B: 0f b6 0c 03 movzbl (%rbx,%rax,1),%ecx
40108F: 88 0c 24 .mov %cl,(%rsp)
401092: 48 8b 14 24 .mov (%rsp),%rdx
401096: 83 e2 0f și $0xf,%edx
401099: 0f b6 92 b0 24 40 00 movzbl 0x4024b0(%rdx),%edx
4010a0: 88 54 04 10 .mov %dl,0x10(%rsp,%rax,1)
4010a4: 48 83 c0 01 adăuga 0x1,%rax
4010A8: 48 83 f8 06 CMP 0x6,%rax
http://webcache.googleusercontent.com/search?q=cache:r7Vvh9Ci4SUJ:blog.carlosgaldino.com/2016/04/28/defusing-a-binary-bomb-with-gdb-part-5.html+&cd... 1/5
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 5 · carlosgaldino
4010ac: 75 DD JNE 40108b <phase_5+0x29>
4010ae: C6 44 24 16 00 movb $0x0,0x16(%rsp)
4010b3: să fie 5e 24 40 00 .mov $0x40245e,%esi
4010b8: 48 8d 7c 24 10 pășune 0x10(%rsp),%CDI
4010bd: E8 76 02 00 00 Apel 401338 <strings_not_equal>
4010C2: 85 c0 testa %EAX,%EAX
4010C4: 74 13 Je 4010d9 <phase_5+0x77>
4010C6: E8 6f 03 00 00 Apel 40143a <explode_bomb>
4010CB: 0f 1f 44 00 00 NOPL 0x0(%rax,%rax,1)
4010d0: EB 07 JMP 4010d9 <phase_5+0x77>
4010d2: b8 00 00 00 00 .mov $0x0,%eax
4010d7: EB B2 JMP 40108b <phase_5+0x29>
4010d9: 48 8b 44 24 18 .mov 0x18(%rsp),%rax
4010de: 64 48 33 04 25 28 00 Xor %FS:0x28,%RAX
4010e5: 00 00
4010e7: 74 05 Je 4010ee <phase_5+0x8c>
4010e9: E8 42 FA FF FF Apel 400B30 <__stack_chk_fail@p
lt>
4010ee: 48 83 c4 20 adăuga $0x20,%rsp
4010F2: 5b pop %rbx
4010F3: C3 Retq
Primele câteva linii configurează stiva pentru această funcție și pe 0x40106a este
configurat protectorul stivei1.
La 0x40108b primul octet din șirul de intrare este copiat în ecx . Observați că la
începutul acestei funcții șirul de intrare stocat pe rdi a fost copiat în rbx la 0x401067
. Instrucțiunea de la 0x40108b folosește atât rbx, cât și rax, dar din moment ce rax
are o valoare de 0, adresa de date utilizată ca sursă va fi exclusiv adresa stocată pe
rbx . O putem confirma cu:
http://webcache.googleusercontent.com/search?q=cache:r7Vvh9Ci4SUJ:blog.carlosgaldino.com/2016/04/28/defusing-a-binary-bomb-with-gdb-part-5.html+&cd... 2/5
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 5 · carlosgaldino
(gdb) i r $ecx
ECX 0x69 105
Apoi, în următoarele două instrucțiuni, acest octet este copiat în rdx și pe 0x401096
la nivel de biți ȘI este efectuat împotriva acestui octet. Valoarea după AND la nivel
de biți este apoi utilizată ca decalaj pentru a copia o valoare dintr-o anumită locație
în același registru edx pe 0x401099 . Aceeași valoare de 1 octet este apoi stocată
într-o variabilă locală pe 0x4010a0 . Următoarea instrucțiune incrementează rax ,
care este apoi verificată de următoarea instrucțiune pentru a vedea dacă acest
proces a fost executat pentru toate caracterele din intrarea noastră. Dacă procesul
nu a fost efectuat pentru toate caracterele, atunci sare din nou la 0x40108b pentru a
citi următorul caracter și a repeta pașii de mai sus.
La sfârșitul acestui proces, o variabilă locală va conține un nou șir care este creat
prin utilizarea caracterelor noastre de intrare ca un decalaj la un șir misterios.
Acum că știm fluxul pentru această fază, este timpul să vedem ce șir de intrare
trebuie să producă.
http://webcache.googleusercontent.com/search?q=cache:r7Vvh9Ci4SUJ:blog.carlosgaldino.com/2016/04/28/defusing-a-binary-bomb-with-gdb-part-5.html+&cd... 3/5
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 5 · carlosgaldino
Acum tot ce avem nevoie este să ne uităm la șirul intermediar pentru a vedea care
sunt compensările pe care trebuie să le introducem, astfel încât șirul final să fie
fluturași .
Privind ieșirea de mai sus, putem ghici că șirul intermediar real trebuie să fie doar
maduiersnfotvbyl . Privind poziția fiecărui caracter, putem verifica apoi dacă
compensările corecte trebuie să fie:
scriso Comp
are ensa
f 0x9
l 0xf
y
0xe
e 0x5
r 0x6
s 0x7
Deci, răspunsul este de fapt orice secvență de caractere ale căror reprezentări de
octeți se termină în 9FE567 .
Având în vedere doar caracterele imprimabile din tabelul ASCII, putem concepe
următorul tabel:
Compe caractere
nsa posibile
0x9 )9IYiyy
0xf / ? O _ o DEL
0xe .>N^n~
0x5 0x6 0x7
Note
1. https://en.wikipedia.org/wiki/Buffer_overflow_protection ↩
http://webcache.googleusercontent.com/search?q=cache:r7Vvh9Ci4SUJ:blog.carlosgaldino.com/2016/04/28/defusing-a-binary-bomb-with-gdb-part-5.html+&cd... 5/5
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 6 · carlosgaldino
Acest post face parte dintr-o serie în care vă arăt cum să dezamorsați o bombă
binară citind codul de asamblare și folosind gdb . S-ar putea să doriți să citiți
prima parte dacă nu ați făcut-o încă.
Iată-ne ajunși la ultima fază. Aceasta este cea mai interesantă fază de până acum.
Codul pentru phase_6 este următorul:
00000000004010f4 <phase_6>:
4010F4 41 56 împinge %r14
4010F6 41 55 împinge %r13
4010F8 41 54 împinge %r12
4010FA 55 împinge %rbp
4010FB 53 împinge %rbx
4010FC 48 83 Ce 50 sub $0x50,%rsp
401100 49 89 E5 .mov %rsp,%r13
401103 48 89 E6 .mov %rsp,%rsi
401106 E8 51 03 00 00 Apel 40145c <read_six_numbers>
40110b 49 89 E6 .mov %rsp,%r14
40110E 41 î.Hr 00 00 00 00 .mov 0x0,%r12d
401114 4c 89 Ed .mov %r13,%rbp
401117 41 8b 45 00 .mov 0x0(%R13),%EAX
40111b 83 E8 01 sub $0x1,%eax
40111E 83 F8 05 CMP $0x5,%eax
401121 76 05 JBE 401128 <phase_6+0x34>
401123 E8 12 03 00 00 Apel 40143a <explode_bomb>
401128 41 83 C4 01 adăuga 0x1,%r12d
40112c 41 83 Fc 06 CMP 0x6,%r12d
401130 74 21 Je 401153 <phase_6+0x5f>
401132 44 89 E3 .mov %R12D,%EBX
401135 48 63 C3 movslq %ebx,%rax
401138 8b 04 84 .mov (%rsp,%rax,4),%eax
40113B 39 45 00 CMP %eax,0x0(%RBP)
40113E 75 05 JNE 401145 <phase_6+0x51>
401140 E8 F5 02 00 00 Apel 40143a <explode_bomb>
401145 83 C3 01 adăuga $0x1,%EBX
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+... 1/15
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 6 · carlosgaldino
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+... 2/15
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 6 · carlosgaldino
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+... 3/15
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 6 · carlosgaldino
4011F5: 75 E8 JNE 4011df <phase_6+0xeb>
4011f7: 48 83 c4 50 adăuga $0x50,%rsp
4011FB: 5b pop %rbx
4011FC: 5D pop %rbp
4011fd: 41 5c pop %r12
4011ff: 41 5d pop %r13
401201: 41 5e pop %r14
401203: C3 Retq
Este mai lung decât celelalte faze și pare mai complicat, așa că îl vom împărți în
părți pentru a explica ce face fiecare parte.
Prima parte la care ne putem uita este unde se inițializează funcția. Începe prin
salvarea unor valori ale registrelor, deoarece acestea vor fi utilizate ca variabile
locale în această funcție, apoi făcând loc altor variabile locale și apoi citind intrarea
care va fi utilizată pentru a dezamorsa faza. La 0x401106 putem vedea că intrarea
pentru această fază trebuie să fie șase numere:
După citirea celor șase numere și plasarea primului pe rsp , codul copiază adresa
care indică primul în r14 , apoi stabilește alte variabile și, în cele din urmă, pe
0x40111e verifică dacă primul număr pe care l-am furnizat este sau nu mai mic sau
egal cu 6 . Cum a făcut asta?
rsi este folosit pentru a reține al doilea argument pentru un apel de funcție și
înainte de apelarea read_six_numbers (cel 0x401103 ) adresa RSP a fost copiată în
RSI
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+... 4/15
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 6 · carlosgaldino
Apoi, la 0x401117 valoarea stocată în adresa de pe r13 , primul nostru număr, este
copiat în eax și apoi codul verifică dacă este mai mic sau egal cu 6 .
După aceea, următorul număr pe care l-am introdus este verificat cu primul. Al
doilea număr este copiat în eax prin această instrucțiune:
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+... 5/15
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 6 · carlosgaldino
Valoarea stocată la această adresă rezultată va fi apoi copiată în eax . Pentru prima
iterație înseamnă al doilea număr de intrare.
Apoi, a doua noastră valoare (pe eax ) este comparată cu prima pentru a vedea
dacă nu sunt egale și sare la următoarea parte:
Primele trei linii vor verifica dacă am făcut această verificare pentru toate cele șase
numere, ceea ce înseamnă că nu putem introduce numere repetate. După aceea, pe
0x40114d , r13 este schimbat pentru a păstra adresa celui de-al doilea număr de
intrare prin adăugarea a 4 octeți ( sizeof(int) ) la adresa pe care r13 o stochează în
prezent. Apoi se întoarce la 0x401114 să facem aceleași verificări față de celelalte
numere pe care le-am furnizat.
Prima linie a acestei părți definește pur și simplu adresa, ceea ce înseamnă că am
iterat peste toate cele șase numere. Primul număr este stocat pe adresa pe care o
deține rsp , iar al șaselea număr va fi pe $rsp + 0x14 (adresa de început + decalaj de
5 int ).
R14 deține, de asemenea, adresa pentru primul număr, deci va fi copiată în Rax
pe 0x401158 pentru a fi utilizată în această iterație. Apoi, pe următoarele două linii,
atât ecx cât și edx stochează valoarea 7 . După configurare, iterația reală va începe
scăzând mai întâi din edx valoarea stocată de adresa în rax (primul nostru număr
din prima iterație). Cel 0x401164 rezultatul acestei scăderi va suprascrie valoarea
pe rax și apoi pe 0x401166 codul va trece la următorul int pe care l-am furnizat,
comparați pe 0x40116d dacă am iterat peste toate cele șase numere și săriți înapoi
la 0x401160 dacă nu am făcut-o, altfel ieșiți din buclă și continuați execuția pe
0x401197 .
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+... 7/15
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 6 · carlosgaldino
Deși prima linie a acestei părți este la 0x401176 , execuția începe de fapt la
0x401197 . După executarea acestei linii, ecx va deține primul număr din matricea
noastră, deoarece valoarea stocată pe rsi este 0 (din 0x40116f ), iar instrucțiunea de
pe 0x401197 înseamnă: copiați valoarea stocată de adresa $rsi*0x1 + $rsp în ecx .
Această operație înseamnă în mod clar că face parte dintr-o iterație și putem ghici
că rsi va fi actualizat în acest proces pentru a trece peste celelalte numere din
matrice.
Dacă numărul curent pe ecx este mai mic sau egal cu 1 , codul va sări la 0x401183 ,
altfel va sări la 0x401176 .
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+... 8/15
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 6 · carlosgaldino
Valorile de pe ecx și eax se vor potrivi numai după șase iterații: în exemplul nostru,
ecx începe cu 6 și eax cu 1 . În acest caz, înainte de a sări la 0x401188 , rdx va
avea orice valoare este stocată în $rdx + 0x48 (de șase ori adăugând 0x8 la adresa
inițială și copiind valoarea din noua adresă în rdx ).
La această linie, adresa pe care rdx o deține va fi copiată la adresa care rezultă din:
$rsi*0x2 + $rsp + 0x20 . RSI este indicele peste iterația care se întâmplă:
Acum, că știm despre ce este vorba despre această iterație, să vedem exact ce este
stocat de adresa inițială pe rdx :
(GDPR) x 0x6032d0
0x6032d0 <nod1>: 0x0000014c
Huh, nod1 , nume interesant, nu? Să vedem ce conține această adresă plus 8 octeți:
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+... 9/15
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 6 · carlosgaldino
(gdb) x 0x6032d0+0x8
0x6032d8 <nod1+8>: 0x006032e0
(GDPR) x 0x6032e0
0x6032e0 <nod2>: 0x000000a8
(GDPR) x 0x6032e0+0x8
0x6032e8 <nod2+8>: 0x006032f0
Și ce stochează node3 :
(gdb) x *(0x6032e0+0x8)
0x6032f0 <nod3>: 0x0000039c
Avem o listă legată care conține o valoare int , identificatorul nodului și indicatorul
către următorul nod, ceva de genul următor:
nod struct {
int x;
int i;
nodul struct *următorul;
};
Deci, atunci când codul sare la 0x401188 , rdx va avea adresa valorii stocate de
node6 , deoarece matricea noastră este 6 5 4 3 2 1 și a trecut
(GDB) I R RDX
Rdx 0x603320 6304544
(GDPR) x 0x6032d0+0x48
0x603318 <nod5+8>: 0x00603320
(GDPR) x $rdx
0x603320 <nod6>: 0x000001bb
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+... 10/15
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 6 · carlosgaldino
Adresa rdx deține, care stochează valoarea 0x1bb , va fi plasată în prima poziție a
unei noi matrice începând de la $rsp + 0x20 . Deoarece acest cod iterează peste
toate cele șase numere, după executarea acestei părți pentru toate numerele,
această nouă matrice va stoca de fapt adresele care dețin valorile pe care nodul
corespunzător le stochează, pe baza matricei noastre de intrare transformate.
Explicând: din 0x401176 până în 0x401181 codul caută nodul corespunzător pentru
iterația curentă. La 0x401188 adresa valorii x pe care o deține nodul este apoi
copiată în indicele curent de iterație din noua matrice. Apoi începe următoarea
iterație.
Să vedem care sunt valorile pe care fiecare nod le stochează și adresele acestora.
Mai întâi definim o comandă pentru a imprima valorile nodului și a trece la
următorul nod:
Definire Plist
set var $n = $arg 0
în timp ce $n
printf "nod%d (%p): valoare = %#.3x, next=%p\n", *($n+0x4), $n, *$n,
*($n+0x8)
set var $n = *($n+0x8)
capăt
capăt
Imprimarea valorilor:
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+... 11/15
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 6 · carlosgaldino
După crearea acestei noi matrice, codul continuă execuția la 0x4011ab care este
următoarea parte:
La prima linie a acestei părți rbx primește valoarea primului element al noii
matrice, care este adresa lui x pentru nod6 . În linia următoare rax primește al
doilea element al noii matrice și în a treia linie rsi primește o adresă care tocmai a
trecut de ultimul element al acestei noi matrice, cel mai probabil pentru a verifica
mai târziu dacă am iterat peste întreaga matrice nouă.
Pe 0x4011ba , rcx va deține valoarea primului element al noii matrice, apoi rdx va
obține a doua valoare și în linia următoare, 0x4011c0 , această valoare va fi copiată
în $rcx + 0x8 . Să facem o copie de rezervă pentru un minut și să vedem valorile din
ambele registre după executarea instrucțiunii la 0x4011c0 :
$rcx + 0x8 este adresa care deține indicatorul către următorul element al listei și
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+... 12/15
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 6 · carlosgaldino
(GDPR) x $rcx+0x8
0x603328 <nod6+8>: 0x0000000000603310
După aceea, pe 0x4011c4 următoarea valoare din noua matrice este plasată în rax
pentru următoarea iterație, care este verificată față de rsi în linia următoare și
procesul se repetă. La sfârșitul acestuia, următorul indicator pentru fiecare nod va fi
modificat în funcție de valorile noii matrice. După cum am văzut mai sus, noua
matrice are următoarele valori:
Aceste valori corespund nodului6 nod5 nod4 nod3 nod2 nod1 deci după iterația de
mai sus indicatorii vor fi modificați pentru a reflecta această ordine. O putem
confirma cu comanda noastră plist după executarea instrucțiunii pe 0x4011d2 :
(GDPR
) plist 0x603320
Nod6 (0x603320): valoare = 0x1bb, următor = 0x603310
nod5 (0x603310): valoare = 0x1dd, următor = 0x603300
nod4 (0x603300): valoare = 0x2b3, următor = 0x6032f0
Nod3 (0x6032f0): valoare = 0x39c, următor = 0x6032e0
Nod2 (0x6032e0): valoare = 0x0a8, următor = 0x6032d0
Node1 (0x6032d0): valoare = 0x14c, next = (zero)
Acum că lista a fost modificată, execuția continuă la 0x4011da prin stocarea valorii
5 în ebp . Apoi, adresa valorii x a următorului nod este stocată pe rax și apoi în linia
următoare valoarea reală x este stocată pe eax (registru pe 32 de biți, deoarece
avem de-a face cu int ). Pe 0x4011e5 valoarea x din primul nod (la rbx ) este
comparată cu valoarea x a celui de-al doilea și dacă prima valoare este mai mare
sau egală cu a doua, codul sare la 0x4011ee care va actualiza valoarea rbx pentru a
indica următoarea valoare x și, de asemenea, va actualiza valoarea ebp care este
apoi comparată pentru a vedea dacă am iterat întreaga listă.
Deci, această iterație verifică dacă valoarea x a nodului curent este mai mare sau
egală cu următorul x pentru toate nodurile din listă. Dacă nu sunt, bomba
explodează după cum putem vedea la 0x4011e9 .
X
nod # x (hex)
(decembri
1 0x14c 332
2 0x0a8 168
3
0x39c 924
4
0x2b3 691
5
0x1dd 477
6 0x1bb 443
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+... 14/15
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 6 · carlosgaldino
924 -> 691 -> 477 -> 443 -> 332 -> 168
nod3 -> nod4 -> nod5 -> nod6 -> nod1 -> nod2
432165
Felicitări! Ai dezamorsat bomba!
Sau nu? Există ceva ciudat în fișierul C. Funcția principală se termină astfel:
intrare = read_line();
phase_6(intrare);
phase_defused();
returnare 0;
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+... 15/15
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 7 · carlosgaldino
Acest post face parte dintr-o serie în care vă arăt cum să dezamorsați o bombă
binară citind codul de asamblare și folosind gdb . S-ar putea să doriți să citiți
prima parte dacă nu ați făcut-o încă.
În ultima postare , bomba a fost dezamorsată, dar era ceva ciudat în fișierul C.
Acesta a fost sfârșitul funcției principale :
intrare = read_line();
phase_6(intrare);
phase_defused();
returnare 0;
phase_defused este o funcție care se numește de fiecare dată când o fază este
dezamorsată, așa că haideți să aruncăm o privire la ea:
00000000004015c4 <phase_defused>:
4015C4: 48 83 CE 78 sub $0x78,%rsp
4015C8: 64 48 8b 04 25 28 00 mov %FS:0x28,%RAX
4015cf: 00 00
http://webcache.googleusercontent.com/search?q=cache:aW_YFEmXe2cJ:blog.carlosgaldino.com/2016/05/24/defusing-a-binary-bomb-with-gdb-part-7.html+... 2/11
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 7 · carlosgaldino
4015d1: 48 89 44 24 68 %rax,0x68(%rsp)
4015d6: 31 c0 mov xor %EAX,%EAX
4015D8: 83 3d 81 21 20 00 06 cmpl $0x6,0x202181(%RIP)
# 603760 <num_input_ șiruri de
4015df: 75 5e caractere> JNE 40163f <phase_defused+0x7b
>
4015e1: 4c 8d 44 24 10 pășune 0x10(%rsp),%r8
4015E6: 48 8d 4c 24 0C pășune 0xc(%rsp),%rcx
4015EB: 48 8d 54 24 08 pășune 0x8(%rsp),%rdx
4015f0: să fie 19 26 40 00 .mov $0x402619,%esi
4015F5: BF 70 38 60 00 .mov $0x603870,%EDI
4015fa: E8 F1 F5 ff ff Apel 400bf0 <__isoc99_sscanf@pl
t>
4015 și 83 f8 03 CMP $0x3,%eax
următoar
401602: 75 31 JNE 401635 <phase_defused+0x71
>
401604: să fie 22 26 40 00 .mov $0x402622,%esi
401609: 48 8d 7c 24 10 pășune 0x10(%rsp),%CDI
40160e: E8 25 FD ff ff Apel 401338 <strings_not_equal>
401613: 85 c0 testa %EAX,%EAX
401615: 75 1e JNE 401635 <phase_defused+0x71
>
401617: BF F8 24 40 00 .mov $0x4024f8,%EDI
40161C: E8 EF F4 ff ff Apel 400B10 <puts@plt>
401621: BF 20 25 40 00 .mov $0x402520,%EDI
401626: E8 E5 F4 ff ff Apel 400B10 <puts@plt>
40162B: B8 00 00 00 00 .mov $0x0,%eax
401630: E8 0d FC ff ff Apel 401242 <secret_phase>
401635: BF 58 25 40 00 .mov $0x402558,%EDI
40163a: E8 D1 F4 ff ff Apel 400B10 <puts@plt>
40163F: 48 8b 44 24 68 .mov 0x68(%rsp),%rax
401644: 64 48 33 04 25 28 00 Xor %FS:0x28,%RAX
40164B: 00 00
40164D: 74 05 Je 401654 <phase_defused+0x90
>
40164F: E8 DC F4 ff ff Apel 400B30 <__stack_chk_fail@p
lt>
401654: 48 83 c4 78 adăuga $0x78,%rsp
401658: C3 Retq
401659: 90 Nop
40165a: 90 Nop
40165B: 90 Nop
40165C: 90 Nop
40165D: 90 Nop
40165e: 90 Nop
40165F: 90 Nop
Primele câteva linii până la 0x4015d8 sunt pentru setarea protectorului stivei1 și
apoi salvarea rax înainte de a-l seta la 0 pe 0x4015d6 . Apoi, pe 0x4015d8
http://webcache.googleusercontent.com/search?q=cache:aW_YFEmXe2cJ:blog.carlosgaldino.com/2016/05/24/defusing-a-binary-bomb-with-gdb-part-7.html+... 2/11
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 7 · carlosgaldino
compară dacă am trecut deja prin toate cele șase faze uitându-ne la numărul de
șiruri de intrare. Această comparație va fi adevărată numai după dezamorsarea
celor șase faze, astfel încât, înainte de ultima postare, codul a sărit întotdeauna la
0x40163f care a restabilit valoarea rax și a verificat protectorul stivei înainte de a
reveni.
Atât edi cât și esi sunt folosite pentru a susține primul și, respectiv, al doilea
argument. Apoi, singurul lucru pe care ambele registre l-au putut stoca au fost
adresele careindicau șirurile 2.
Sscanf este apoi folosit pentru a scana din nou intrarea celei de-a patra faze, dar
cu un format diferit acum, așteptând un șir după a doua valoare. Puteți vedea că pe
0x4015ff dacă nu vede 3 valori, sare la 0x401635 care va imprima următorul mesaj
și va returna:
http://webcache.googleusercontent.com/search?q=cache:aW_YFEmXe2cJ:blog.carlosgaldino.com/2016/05/24/defusing-a-binary-bomb-with-gdb-part-7.html+... 2/11
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 7 · carlosgaldino
$3 = 0x402558 "Felicitări! Ai dezamorsat bomba!"
În caz contrar, această funcție se va compara dacă am introdus șirul corect pentru
a activa faza secretă. Privind instrucțiunile de pe 0x401604 putem vedea care este
adresa șirului de activare:
Dacă intrarea pentru faza 4 include DrEvil la sfârșit, codul va apela apoi faza
secretă pe 0x401630 :
0000000000401242 <secret_phase>:
401242: 53 împinge %rbx
401243: E8 56 02 00 00 Apel 40149e <read_line>
401248: Ba 0a 00 00 00 .mov $0xa,%EDX
40124D: fi 00 00 00 00 .mov $0x0,%esi
401252: 48 89 C7 .mov %rax,%CDI
401255: E8 76 F9 Ff Ff Apel 400bd0 <strtol@plt>
40125a: 48 89 C3 .mov %rax,%rbx
40125d: 8D 40 Ff pășune -0x1(%rax),%EAX
401260: .3d E8 03 00 00 CMP $0x3e8,%eax
401265: 76 05 JBE 40126C <secret_phase+0x2a>
401267: E8 CE 01 00 00 Apel 40143a <explode_bomb>
40126C: 89 de .mov %ebx,%esi
40126e: Bf f0 30 60 00 .mov $0x6030f0,%EDI
401273: E8 8c Ff Ff Ff Apel 401204 <distracție7>
401278: 83 F8 02 CMP $0x2,%eax
40127b: 74 05 Je 401282 <secret_phase+0x40>
40127D: E8 b8 01 00 00 Apel 40143a <explode_bomb>
401282: Bf 38 24 40 00 .mov $0x402438,%EDI
401287: E8 84 F8 Ff Ff Apel 400B10 <puts@plt>
40128C: E8 33 03 00 00 Apel 4015c4 <phase_defused>
401291: 5b pop %rbx
401292: C3 Retq
401293: 90 Nop
401294: 90 Nop
401295: 90 Nop
http://webcache.googleusercontent.com/search?q=cache:aW_YFEmXe2cJ:blog.carlosgaldino.com/2016/05/24/defusing-a-binary-bomb-with-gdb-part-7.html+... 2/11
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 7 · carlosgaldino
401296: 90 Nop
401297: 90 Nop
401298: 90 Nop
401299: 90 Nop
40129a: 90 Nop
40129B: 90 Nop
40129C: 90 Nop
40129d: 90 Nop
40129E: 90 Nop
40129F: 90 Nop
După citirea intrării pentru această fază secretă pe 0x401243 , edx va stoca valoarea
10 , esi va stoca NULL și rdi va stoca intrarea pe care am dat-o. Apoi strtol 3 va fi
apelat pe 0x401255 și judecând după valorile din registre, înseamnă că intrarea
noastră va fi convertită într-un număr în baza 10. După aceea, pe 0x40125a
numărul deja convertit va fi stocat pe rbx . Pe 0x40125d valoarea va fi modificată
scăzând 1 și plasată din nou pe eax . Apoi, o comparație cu 0x3e8 care este 1000 în
baza 10 . Dacă intrarea noastră este mai mică de 1000 , codul va sări la 0x40126c
pentru a continua și, dacă nu, bomba va exploda.
La 0x40126c valoarea noastra este plasata pe esi si edi primeste o adresa. Ambele
valori vor fi utilizate in urmatoarea functie fun7 care se numeste pe 0x401273 .
Rezultatul că fun7 trebuie să se întoarcă este 2 după cum puteți vedea pe 0x401278 .
(GDPR) x 0x6030f0
0x6030f0 <n1>: 0x00000024
Hmm, n1 . Acest nume nu oferă niciun indiciu despre ce este exact acest lucru. Să
ne uităm la distracție7 atunci:
0000000000401204 <distracție7>:
401204: 48 83 CE 08 sub $0x8,%rsp
401208: 48 85 Ff testa %rdi,%CDI
40120b: 74 2b Je 401238
40120D: 8b 17 .mov <distracție7+0x34>
(%rdi),%edx
40120f: 39 F2 CMP %ESI,%EDX
401211: 7e 0d JLE 401220 <distracție7+0x1c>
401213: 48 8b 7f 08 .mov 0x8(%rdi),%CDI
401217: E8 E8 FF FF Apel 401204 <distracție7>
40121C: 01 c0 adăuga %EAX,%EAX
http://webcache.googleusercontent.com/search?q=cache:aW_YFEmXe2cJ:blog.carlosgaldino.com/2016/05/24/defusing-a-binary-bomb-with-gdb-part-7.html+... 2/11
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 7 · carlosgaldino
40121e: EB 1D JMP 40123d <distracție7+0x39>
401220: b8 00 00 00 00 .mov $0x0,%eax
401225: 39 f2 CMP %ESI,%EDX
401227: 74 14 Je 40123d <distracție7+0x39>
401229: 48 8b 7f 10 .mov 0x10(%rdi),%CDI
40122d: E8 d2 ff ff ff Apel 401204 <distracție7>
401232: 8d 44 00 01 pășune 0x1(%rax,%rax,1),%eax
401236: EB 05 JMP 40123d <distracție7+0x39>
401238: B8 ff ff ff ff .mov $0xffffffff,%eax
40123d: 48 83 c4 08 adăuga $0x8,%rsp
401241: C3 Retq
Mai întâi verifică dacă rdi este NULL ( 0x0 ) și dacă este funcția va returna valoarea
-1 ( 0xffffffff la 0x401238 ). Dacă nu, valoarea stocată în adresa rdi stocată va fi
plasată pe edx și apoi comparată (pe 0x40120f ) cu numărul nostru de intrare. Dacă
valoarea de pe edx este mai mică sau egală cu numărul nostru, codul merge la
0x401220 , dacă nu, continuă pe 0x401213 . Să continuăm 0x401213 apoi să ne
întoarcem să vedem ce se întâmplă în cealaltă ramură.
Pe 0x401213 rdi va stoca orice este 8 octeți după adresa deja pe rdi și apela fun7 din
nou.
În cealaltă ramură, când numărul de pe edx este mai mic sau egal cu numărul
nostru, codul merge la 0x401220 care setează eax la 0 , compară ceea ce este pe edx
cu numărul nostru și dacă sunt egale, merge la 0x40123d care se întoarce. Dacă
numerele sunt diferite, atunci instrucțiunea de la 0x401229 va schimba rdi pentru a
stoca orice este de 16 octeți după adresa curentă pe care o are și apoi apelați fun7
așa cum face cealaltă ramură.
În fiecare ramură, CDI este modificat pentru a menține noua adresă localizată fie
8, fie 16 octeți după adresa curentă. Primul lucru pe care îl deține RDI este un
număr, celelalte două sunt indicatori, deci acesta ar putea fi un arbore binar:
nod struct { int data; nodul struct *stânga; nodul struct *dreapta;
};
Nodul rădăcină, situat la adresa inițială cu care este apelat fun7 , este următorul:
(GDPR) x 0x6030f0
0x6030f0 <n1>: 0x00000024
http://webcache.googleusercontent.com/search?q=cache:aW_YFEmXe2cJ:blog.carlosgaldino.com/2016/05/24/defusing-a-binary-bomb-with-gdb-part-7.html+... 2/11
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 7 · carlosgaldino
(GDPR) x 0x6030f0+0x8
0x6030f8 <n1+8>: 0x00603110
(GDPR) x 0x6030f0+0x10
0x603100 <n1+16>: 0x00603130
Știm cum este structurat copacul, dar nu știm ce trebuie să facem pentru a ajunge
la răspunsul corect. secret_phase apelează fun7 și se așteaptă să returneze valoarea 2
:
http://webcache.googleusercontent.com/search?q=cache:aW_YFEmXe2cJ:blog.carlosgaldino.com/2016/05/24/defusing-a-binary-bomb-with-gdb-part-7.html+... 2/11
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 7 · carlosgaldino
401208: 48 85 ff %rdi,%CDI
test je
40120b: 74 2b 401238 <distracție7+0x34>
Și:
Ambele arată că funcția revine atunci când am ajuns la un indicator NULL (primul
caz) sau dacă numărul pe care l-am dat este egal cu cel din nodul curent (al doilea
caz).
Dar, în primul caz, codul sare la 0x401238 care setează valoarea returnată la
-1 :
401238: B8 ff ff ff ff mov
$0xffffffff,%eax
40123D: 48 83 C4 08 adaug
$0x8,%rsp
401241: C3 ă retq
Deci, dacă furnizăm un număr care nu este prezent în arbore, codul va ajunge la un
indicator NULL și va returna -1 , iar dacă numărul nostru este prezent, acesta va
returna 0 .
Acesta este cazul când numărul nostru este mai mic decât valoarea curentă a nodului.
Pur și simplu dublează valoarea returnată (pe 0x40121c ) și sare la 0x40123d pentru a
returna.
În cealaltă ramură, când numărul nostru este mai mare sau egal cu valoarea curentă a
nodului, merge la 0x401220 :
Aici, dacă valorile sunt egale, funcția va returna 0 așa cum am văzut mai devreme, dar
dacă sunt diferite, fun7 va fi apelat din nou și valoarea returnată din apelul interior va
fi dublată ca în cealaltă ramură, dar în acest caz va adăuga și 1 la ea:
Simplificarea:
EAX = 2*RAX + 1
http://webcache.googleusercontent.com/search?q=cache:aW_YFEmXe2cJ:blog.carlosgaldino.com/2016/05/24/defusing-a-binary-bomb-with-gdb-part-7.html+... 9/11
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 7 · carlosgaldino
Privind din nou structura arborescentă, putem încerca să ghicim ce valoare va oferi
răspunsul corect vizitând nodurile corecte.
O opțiune este să vizitați 0x8 și 0x16 . Înlocuind adresele nodului cu datele reale pe
care le au, am avea următoarele apeluri la distracție7 :
http://webcache.googleusercontent.com/search?q=cache:aW_YFEmXe2cJ:blog.carlosgaldino.com/2016/05/24/defusing-a-binary-bomb-with-gdb-part-7.html+... 2/11
5/29/2016 Dezamorsarea unei bombe binare cu gdb - Partea 7 · carlosgaldino
Există un alt răspuns posibil pentru această fază și găsirea ei este lăsată ca un
exercițiu cititorului.
Note
2. https://en.wikipedia.org/wiki/Buffer_overflow_protection ↩
https://en.wikipedia.org/wiki/Buffer_overflow_protection
4. Dacă doriți să aflați mai multe despre lea , diferența sa cu mov , cum și de ce
operațiile aritmetice pot fi efectuate cu lea puteți începe prin citirea următoarei
pagini:
https://en.wikibooks.org/wiki/X86_Assembly/Data_Transfer#Load_Effe
ctive_Address ↩
http://webcache.googleusercontent.com/search?q=cache:aW_YFEmXe2cJ:blog.carlosgaldino.com/2016/05/24/defusing-a-binary-bomb-with-gdb-part-7.html+... 2/11