pwnable.kr之collision
 
pwnable.kr 上的第二道题
0x00 collision
和第一道题一样使用ssh连上去
ssh col@pwnable.kr -p2222 (pw:guest)
查看文件
col@ubuntu:~$ ls -l
total 16
-r-sr-x--- 1 col_pwn col 7341 Jun 11 2014 col
-rw-r--r-- 1 root root 555 Jun 12 2014 col.c
-r--r----- 1 col_pwn col_pwn 52 Jun 11 2014 flag
同样查看源代码,这次比之前的代码要长一些,但是也并不复杂,只要注意关键函数check_password就行
col@ubuntu:~$ cat col.c
#include <stdio.h>
#include <string.h>
unsigned long hashcode = 0x21DD09EC;
unsigned long check_password(const char* p){
int* ip = (int*)p;
int i;
int res=0;
for(i=0; i<5; i++){
res += ip[i];
}
return res;
}
int main(int argc, char* argv[]){
if(argc<2){
printf("usage : %s [passcode]\n", argv[0]);
return 0;
}
if(strlen(argv[1]) != 20){
printf("passcode length should be 20 bytes\n");
return 0;
}
if(hashcode == check_password( argv[1] )){
system("/bin/cat flag");
return 0;
}
else
printf("wrong passcode.\n");
return 0;
}
check_password的功能就是把输入的字符串转化成int类型然后求和返回,我们要拿到flag就需要让这个和等于0x21DD09EC
每个int占4字节,一个char占1个字节,所以没四个char转换成一个int,这里我将结果0x21DD09EC的从低位起拿出两位是一个字节,然后将这个值除以5,如果这个数的范围在可见字符中,这个字符就是结果的字符附近(当然你可以爆破,这题的结果应该不是唯一的),如果不是可见字符(这个值比较小,那就向上一位借1再除以5),由低到高一次计算得出以下结果
9_4b9_4b9_4b1e4bAZ8d
但是将结果输入进去是错的,我将代码在本地编译并使用gdb调试可以发现算出来的结果是
[----------------------------------registers-----------------------------------]
EAX: 0xed09dd1d
EBX: 0xffffd400 --> 0x2
ECX: 0x2a04
EDX: 0x10
ESI: 0x0
EDI: 0x0
EBP: 0xffffd3e8 --> 0x0
ESP: 0xffffd3d0 --> 0xffffd634 ("9_4b9_4b9_4b1e4bAZ8d")
EIP: 0x804853e (<main+116>: add esp,0x10)
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x8048535 <main+107>: sub esp,0xc
0x8048538 <main+110>: push eax
0x8048539 <main+111>: call 0x804848b <check_password>
=> 0x804853e <main+116>: add esp,0x10
0x8048541 <main+119>: mov edx,eax
0x8048543 <main+121>: mov eax,ds:0x80498b8
0x8048548 <main+126>: cmp edx,eax
0x804854a <main+128>: jne 0x8048563 <main+153>
[------------------------------------stack-------------------------------------]
0000| 0xffffd3d0 --> 0xffffd634 ("9_4b9_4b9_4b1e4bAZ8d")
0004| 0xffffd3d4 --> 0xffffd494 --> 0xffffd60b ("/root/D/other/simple/pwnable.kr-col/test")
0008| 0xffffd3d8 --> 0xffffd4a0 --> 0xffffd649 ("XDG_VTNR=7")
0012| 0xffffd3dc --> 0xf7e3c39d (<__cxa_atexit+29>: test eax,eax)
0016| 0xffffd3e0 --> 0xffffd400 --> 0x2
0020| 0xffffd3e4 --> 0xf7fb1000 --> 0x1a5da8
0024| 0xffffd3e8 --> 0x0
0028| 0xffffd3ec --> 0xf7e24a63 (<__libc_start_main+243>: mov DWORD PTR [esp],eax)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x0804853e in main ()
算出的结果是0xed09dd1d和要求的值很像,只是位置的问题,想起来这是机器大小端的问题,所以讲输入的字符串调整大小端,结果为b4_9b4_9b4_9b4e4d8ZA
col@ubuntu:~$ ./col b4_9b4_9b4_9b4e4d8ZA
daddy! I just managed to create a hash collision :)
0x01总结
了解了内存中大小端,数据类型在内存的表示