文章目录
  1. 1. 0x00 collision
  2. 2. 0x01总结

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总结

了解了内存中大小端,数据类型在内存的表示

文章目录
  1. 1. 0x00 collision
  2. 2. 0x01总结