user / serial : meoluoi / 9118715
int __cdecl main() { char szName[72]; char szInputSerial[64]; int idx; char szRealSerial[64]; cout << "-> Small crackme for Stingduk <-" << endl; cout << ""Give me your name (max 50 chars): "; cin >> szName; cout << "Pass me the serial (max 50 chars): "; cin >> szInputSerial; idx = 0; while (szName[idx] != 0) { char ch = szName[idx]; szRealSerial[idx++] = ch % 10 + 48; } szRealSerial[idx] = 0; if (0 != strcmp(szRealSerial, szInputSerial)) { cout << "No luck here mate :(" << endl; } else { cout << "Great work!" << endl; } return 0; }
$ file small small: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped--> Trông cái executable thấy bình thường, em nghĩ hình nó ko bị pack (ko biết đúng ko?) Bác nào có kinh nghiệm về detect các packer trong linux xin chia sẻ. B2:
$ gdb ./small -q Using host libthread_db library "/lib/libthread_db.so.1". (gdb) disassemble main Dump of assembler code for function main: 0x080487bc <main+0>: push %ebp 0x080487bd <main+1>: mov %esp,%ebp 0x080487bf <main+3>: sub $0xe8,%esp ......................... ......................... 0x080488c4 <main+264>: push %eax ; fake serial 0x080488c5 <main+265>: push %edx ; real serial 0x080488c6 <main+266>: call 0x8048668 <strcmp@plt> ;bp here 0x080488cb <main+271>: add $0x10,%esp 0x080488ce <main+274>: test %eax,%eax 0x080488d0 <main+276>: jne 0x80488fa <main+318> ; Nhảy đến Bad boy nếu sai serial, có thể patch tại đây 0x080488d2 <main+278>: sub $0x8,%esp 0x080488d5 <main+281>: push $0x80486d8 ---Type <return> to continue, or q <return> to quit---return 0x080488da <main+286>: sub $0xc,%esp 0x080488dd <main+289>: push $0x8048b84 ; Great work! 0x080488e2 <main+294>: push $0x8049db8 0x080488e7 <main+299>: call 0x8048698 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt> 0x080488ec <main+304>: add $0x14,%esp 0x080488ef <main+307>: push %eax 0x080488f0 <main+308>: call 0x8048658 <_ZNSolsEPFRSoS_E@plt> 0x080488f5 <main+313>: add $0x10,%esp 0x080488f8 <main+316>: jmp 0x8048920 <main+356> 0x080488fa <main+318>: sub $0x8,%esp 0x080488fd <main+321>: push $0x80486d8 0x08048902 <main+326>: sub $0xc,%esp 0x08048905 <main+329>: push $0x8048b90 ; No luck here mate :( 0x0804890a <main+334>: push $0x8049db8B3:
(gdb) break *main+266 Breakpoint 1 at 0x80488c6 (gdb) run Starting program: /usr/local/src/crackme/small -> Small crackme for Stingduk <- Give me your name (max 50 chars): hvaonline.net Pass me the serial (max 50 chars): 123456 Breakpoint 1, 0x080488c6 in main () (gdb) i r eax 0xbfb03a80 -1078969728 ecx 0xbfb03a4c -1078969780 edx 0xbfb03a40 -1078969792 ebx 0xb7ed3ff4 -1209188364 esp 0xbfb03a10 0xbfb03a10 ebp 0xbfb03b08 0xbfb03b08 esi 0xb7fedce0 -1208034080 edi 0x0 0 eip 0x80488c6 0x80488c6 <main+266> eflags 0x200296 [ PF AF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51 (gdb) x/s $eax 0xbfb03a80: "123456" <-- FAke Serial (gdb) x/s $edx 0xbfb03a40: "4871085016016" <-- Real Serial...!!! Done Vậy là ta mới câu được
hvaonline.net / 4871085016016Xin mời các bác thảo luận tiếp :) ]]>
Cho tui khai trương trước, crack thì tui hơi lười, chỉ RE ra source để bà con crack tiếp ;) Code:Ok, đây là cách solve thứ 2: Nhìn đoạn code mà anh TQN đã decompiler, chúng ta sẽ tận dụng lỗi buffer overflow do cin đọc vào. 1. Chúng ta tận dụng làm tràn bộ đệm của szName[72], hoặc szInputSerial[64]; Điều cần làm trước tiên là phải tính toán chính xác cần đủ bao nhiêu byte để ghi đè lên con trỏ EIP. Chúng ta hãy hình dung stack như sau
Crackme này đơn giản, chỉ làm nhiêu đó thôi. Tool: IDA + HexRays. Thời gian đọc, phân tích: 2 phút. Thời gian copy&paste: 30 phút. Cái này mới lâu nè, làm biếng mà.int __cdecl main() { char szName[72]; char szInputSerial[64]; int idx; char szRealSerial[64]; cout << "-> Small crackme for Stingduk <-" << endl; cout << ""Give me your name (max 50 chars): "; cin >> szName; cout << "Pass me the serial (max 50 chars): "; cin >> szInputSerial; idx = 0; while (szName[idx] != 0) { char ch = szName[idx]; szRealSerial[idx++] = ch % 10 + 48; } szRealSerial[idx] = 0; if (0 != strcmp(szRealSerial, szInputSerial)) { cout << "No luck here mate :(" << endl; } else { cout << "Great work!" << endl; } return 0; }
High mem (đáy stack) ....... ....... EIP EBP szName[72]; szInputSerial[64]; idx ...... Low mem (đỉnh stack)Nhìn cấu trúc stack trên ta dễ dàng phán đoán, nếu khai thác vào phần input username của bộ đệm szName[72] chúng ta cần 72 + 4 (EBP)+ 4(EIP) =80byte để ghi đè đủ vừa khít lên 4 byte EIP Tương tự cần 64+72+4+4=142 byte ghi đè vừa khít lên 4 byte EiP (thôi coi đá banh, mai post tiếp :D ]]>
Nếu chỉ cần hiện ra "Great work!" thì có cách đơn giản thế này: $ python -c 'print "\x00\x0a\x00\x0a"' | ./small -> Small crackme for Stingduk <- Give me your name (max 50 chars): Pass me the serial (max 50 chars): Great work!HOW? -:-) -:-) -:-) ]]>
Nếu chỉ cần hiện ra "Great work!" thì có cách đơn giản thế này: $ python -c 'print "\x00\x0a\x00\x0a"' | ./small -> Small crackme for Stingduk <- Give me your name (max 50 chars): Pass me the serial (max 50 chars): Great work!Trường hợp của bạn mrro là một tình huống đặc biệt của keygen :-/ và \x0a tương đương với "\r\n" :-/ :-/ Nên dùng python để input cái serial của bạn mèo thì cũng có thể làm thế này ? Code:
python -c 'print "meoluoi\x0a9118715\x0a"' |./small
python -c 'print "\x00\x20\x00"' |./small
$ gdb --write ./small -q Using host libthread_db library "/lib/libthread_db.so.1". (gdb) disassemble main Dump of assembler code for function main: 0x080487bc <main+0>: push %ebp 0x080487bd <main+1>: mov %esp,%ebp 0x080487bf <main+3>: sub $0xe8,%esp ......................... ......................... 0x080488c4 <main+264>: push %eax ; fake serial 0x080488c5 <main+265>: push %edx ; real serial 0x080488c6 <main+266>: call 0x8048668 <strcmp@plt> ;bp here 0x080488cb <main+271>: add $0x10,%esp 0x080488ce <main+274>: test %eax,%eax 0x080488d0 <main+276>: jne 0x80488fa <main+318> ; Nhảy đến Bad boy nếu sai serial, có thể patch tại đây 0x080488d2 <main+278>: sub $0x8,%esp 0x080488d5 <main+281>: push $0x80486d8 ---Type <return> to continue, or q <return> to quit---return 0x080488da <main+286>: sub $0xc,%esp 0x080488dd <main+289>: push $0x8048b84 ; Great work! 0x080488e2 <main+294>: push $0x8049db8 0x080488e7 <main+299>: call 0x8048698 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt> 0x080488ec <main+304>: add $0x14,%esp 0x080488ef <main+307>: push %eax 0x080488f0 <main+308>: call 0x8048658 <_ZNSolsEPFRSoS_E@plt> 0x080488f5 <main+313>: add $0x10,%esp 0x080488f8 <main+316>: jmp 0x8048920 <main+356> 0x080488fa <main+318>: sub $0x8,%esp 0x080488fd <main+321>: push $0x80486d8 0x08048902 <main+326>: sub $0xc,%esp 0x08048905 <main+329>: push $0x8048b90 ; No luck here mate 0x0804890a <main+334>: push $0x8049db8 ------ (gdb) x/x *0x080488d0 0xec832875: Cannot access memory at address 0xec832875 (gdb) set {int} 0x080488d0=0xec832874 (gdb) quit
$ ./small -> Small crackme for Stingduk <- Give me your name (max 50 chars): hello-world Pass me the serial (max 50 chars): gudbye-world Great work!