Enfin de retour sur Internet après quelques semaines d'absence :).
Je me suis remis à faire des challenges et je vais ici parler d'un wargame qui m'a
bien plu : http://blackbox.smashthestack.org:85/.
Il y a des failles classiques mais présentées d'une manière un peu plus intelligente.
Nous allons commencer par le level1 :
level1@blackbox:~$ ./login2 Username: aa Password: aa Invalid username or password
A partir de là on peut déjà avoir une petite idée de ce que le programme fait,
il y a surement une utilisation d'un strcmp() ou strncmp() simple (nous somme
au level1 après tout :)).
Voyons le code ASM.
level1@blackbox:~$ gdb login2 GNU gdb 6.4.90-debian Copyright (C) 2006 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i486-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) disassemble main Dump of assembler code for function main: 0x0804827a <main+0>: lea 0x4(%esp),%ecx 0x0804827e <main+4>: and $0xfffffff0,%esp 0x08048281 <main+7>: pushl 0xfffffffc(%ecx) 0x08048284 <main+10>: push %ebp 0x08048285 <main+11>: mov %esp,%ebp 0x08048287 <main+13>: push %ebx 0x08048288 <main+14>: push %ecx 0x08048289 <main+15>: sub $0x30,%esp 0x0804828c <main+18>: lea 0xfffffff4(%ebp),%eax 0x0804828f <main+21>: mov %eax,(%esp) 0x08048292 <main+24>: call 0x8072ec0 <_ZNSsC1Ev> 0x08048297 <main+29>: lea 0xfffffff0(%ebp),%eax 0x0804829a <main+32>: mov %eax,(%esp) 0x0804829d <main+35>: call 0x8072ec0 <_ZNSsC1Ev> 0x080482a2 <main+40>: movl $0x80ffe48,0x4(%esp) 0x080482aa <main+48>: movl $0x8130f60,(%esp) 0x080482b1 <main+55>: call 0x806d8f0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc> 0x080482b6 <main+60>: lea 0xfffffff4(%ebp),%eax 0x080482b9 <main+63>: mov %eax,0x4(%esp) 0x080482bd <main+67>: movl $0x8130ec0,(%esp) 0x080482c4 <main+74>: call 0x806b2e0 <_ZSt7getlineIcSt11char_traitsIcESaIcEERSt13basic_istreamIT_T0_ES7_RSbIS4_S5_T1_E> 0x080482c9 <main+79>: movl $0x80ffe53,0x4(%esp) 0x080482d1 <main+87>: movl $0x8130f60,(%esp) 0x080482d8 <main+94>: call 0x806d8f0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc> 0x080482dd <main+99>: lea 0xfffffff0(%ebp),%eax 0x080482e0 <main+102>: mov %eax,0x4(%esp) 0x080482e4 <main+106>: movl $0x8130ec0,(%esp) 0x080482eb <main+113>: call 0x806b2e0 <_ZSt7getlineIcSt11char_traitsIcESaIcEERSt13basic_istreamIT_T0_ES7_RSbIS4_S5_T1_E> 0x080482f0 <main+118>: movl $0x80ffe5e,0x4(%esp) 0x080482f8 <main+126>: lea 0xfffffff4(%ebp),%eax 0x080482fb <main+129>: mov %eax,(%esp) 0x080482fe <main+132>: call 0x80483ee <_ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_EPKS3_> 0x08048303 <main+137>: xor $0x1,%al 0x08048305 <main+139>: test %al,%al 0x08048307 <main+141>: jne 0x8048328 <main+174> 0x08048309 <main+143>: movl $0x80ffe65,0x4(%esp) 0x08048311 <main+151>: lea 0xfffffff0(%ebp),%eax 0x08048314 <main+154>: mov %eax,(%esp) 0x08048317 <main+157>: call 0x80483ee <_ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_EPKS3_> 0x0804831c <main+162>: xor $0x1,%al 0x0804831e <main+164>: test %al,%al 0x08048320 <main+166>: jne 0x8048328 <main+174> 0x08048322 <main+168>: movb $0x1,0xffffffe7(%ebp) 0x08048326 <main+172>: jmp 0x804832c <main+178> 0x08048328 <main+174>: movb $0x0,0xffffffe7(%ebp) 0x0804832c <main+178>: movzbl 0xffffffe7(%ebp),%eax 0x08048330 <main+182>: test %al,%al 0x08048332 <main+184>: je 0x8048366 <main+236> 0x08048334 <main+186>: movl $0x80ffe6e,0x4(%esp) 0x0804833c <main+194>: movl $0x8130f60,(%esp) 0x08048343 <main+201>: call 0x806d8f0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc> 0x08048348 <main+206>: movl $0x806e0c0,0x4(%esp) 0x08048350 <main+214>: mov %eax,(%esp) 0x08048353 <main+217>: call 0x806bf10 <_ZNSolsEPFRSoS_E> 0x08048358 <main+222>: movl $0x80ffe80,(%esp) 0x0804835f <main+229>: call 0x80b5ab0 <system> 0x08048364 <main+234>: jmp 0x804838a <main+272> 0x08048366 <main+236>: movl $0x80ffe88,0x4(%esp) 0x0804836e <main+244>: movl $0x8130f60,(%esp) 0x08048375 <main+251>: call 0x806d8f0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc> 0x0804837a <main+256>: movl $0x806e0c0,0x4(%esp) 0x08048382 <main+264>: mov %eax,(%esp) 0x08048385 <main+267>: call 0x806bf10 <_ZNSolsEPFRSoS_E> 0x0804838a <main+272>: lea 0xfffffff0(%ebp),%eax 0x0804838d <main+275>: mov %eax,(%esp) 0x08048390 <main+278>: call 0x8074e40 <_ZNSsD1Ev> 0x08048395 <main+283>: jmp 0x80483ad <main+307> 0x08048397 <main+285>: mov %eax,0xffffffdc(%ebp) 0x0804839a <main+288>: mov 0xffffffdc(%ebp),%ebx 0x0804839d <main+291>: lea 0xfffffff0(%ebp),%eax 0x080483a0 <main+294>: mov %eax,(%esp) 0x080483a3 <main+297>: call 0x8074e40 <_ZNSsD1Ev> 0x080483a8 <main+302>: mov %ebx,0xffffffdc(%ebp) 0x080483ab <main+305>: jmp 0x80483c5 <main+331> 0x080483ad <main+307>: lea 0xfffffff4(%ebp),%eax 0x080483b0 <main+310>: mov %eax,(%esp) 0x080483b3 <main+313>: call 0x8074e40 <_ZNSsD1Ev> 0x080483b8 <main+318>: mov $0x0,%eax 0x080483bd <main+323>: mov %eax,0xffffffe0(%ebp) 0x080483c0 <main+326>: jmp 0x80483e1 <main+359> 0x080483c2 <main+328>: mov %eax,0xffffffdc(%ebp) 0x080483c5 <main+331>: mov 0xffffffdc(%ebp),%ebx 0x080483c8 <main+334>: lea 0xfffffff4(%ebp),%eax 0x080483cb <main+337>: mov %eax,(%esp) 0x080483ce <main+340>: call 0x8074e40 <_ZNSsD1Ev> 0x080483d3 <main+345>: mov %ebx,0xffffffdc(%ebp) 0x080483d6 <main+348>: mov 0xffffffdc(%ebp),%eax 0x080483d9 <main+351>: mov %eax,(%esp) 0x080483dc <main+354>: call 0x80a5180 <_Unwind_Resume> 0x080483e1 <main+359>: mov 0xffffffe0(%ebp),%eax 0x080483e4 <main+362>: add $0x30,%esp 0x080483e7 <main+365>: pop %ecx 0x080483e8 <main+366>: pop %ebx 0x080483e9 <main+367>: pop %ebp 0x080483ea <main+368>: lea 0xfffffffc(%ecx),%esp 0x080483ed <main+371>: ret End of assembler dump.
On peut remarquer qu'il y a des noms de fonctions étranges, non compréhensible.
Après un peu de recherche, on se rend vite compte que c'est du à un mécanisme qu'on
appelle le name mangling. Ca permet entre autre le polymorphisme. C'est donc un
bon indicateur que le language utilisé est du C++.
Vu que le programme a été compilé avec G++, on va voir comment démangleer ça.
Le tool nécessaire au demangling de noms G++ est c++filt qui est fourni dans la
suite GNU.
Par exemple :
level1@blackbox:~$ c++filt _ZNSsC1Ev std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string()
La fonction que l'on cherche est l'implémentation de l'opérateur ==.
Après un peu de recherche :
level1@blackbox:~$ c++filt _ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_EPKS3_ bool std::operator==<char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*)
On va voir que l'opérateur == est utilisé 2 fois : une fois pour le nom de l'user
et une fois pour le password.
La partie intéressante :
0x080482f0 <main+118>: movl $0x80ffe5e,0x4(%esp) 0x080482f8 <main+126>: lea 0xfffffff4(%ebp),%eax 0x080482fb <main+129>: mov %eax,(%esp) 0x080482fe <main+132>: call 0x80483ee <_ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_EPKS3_> 0x08048303 <main+137>: xor $0x1,%al 0x08048305 <main+139>: test %al,%al 0x08048307 <main+141>: jne 0x8048328 <main+174> 0x08048309 <main+143>: movl $0x80ffe65,0x4(%esp) 0x08048311 <main+151>: lea 0xfffffff0(%ebp),%eax 0x08048314 <main+154>: mov %eax,(%esp) 0x08048317 <main+157>: call 0x80483ee <_ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_EPKS3_>
On a deux emplacement statique dans le binaire : 0x80ffe5e et 0x80ffe65.
On les extraits et on a : level2 et PassFor2. Comme vous pouvez vous en douter,
on vient de trouver l'utilisateur et le mot de passe pour le niveau suivant ;).
Pour la reconstruction du code, on doit avoir quelque chose de pas très loin de ça :
#include <iostream> #include <string> using namespace std; int main (int argc, char *argv[]) { string username, password; cout << "Username: "; cin >> username; cout << endl << "Password: "; cin >> password; if (username == "level2" && password == "PassFor2") system("/bin/sh"); else cout << "Invalid username or password"; return 0; }
Et voilà :).
Nous passons directement au niveau 3 vu que le niveau 2 est un simple buffer overflow (utilisez pattern_create, pattern_offset et gdb comme expliqués dans les autres articles ;)).
m_101
Aucun commentaire :
Enregistrer un commentaire