Web狗的Pwnable

了解了解下pwn

fd – 1 pt

1
2
3
4
5
Mommy! what is a file descriptor in Linux?
* try to play the wargame your self but if you are ABSOLUTE beginner, follow this tutorial link: https://www.youtube.com/watch?v=blAxTfcW9VU
ssh fd@pwnable.kr -p2222 (pw:guest)

主要的三个文件fd、fd.c、flag设置着不同的权限,fd是一个可执行文件,以下为fd.c的代码

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;
}

因为初次接触linux C,所以对第五行的代码main中的参数进行详细查询。

  • int argc指执行程序时命令行的参数个数
  • argv[]数组用于存放命令行中参数的具体值
  • 这道题如果键入的参数个数小于2个的话程序就会输出”pass argv[1] a number\n”让我们给第二个参数一个具体的数值.
    第十行描述的是通过 argv[1] 获取一字符串并使用 atoi() 函数将其转化为整型于 0x1234 (十进制的4660)作差,其结果赋值给整型变量 fd 。在linux C下read()函数是涉及到了文件描述的函数,这里指的是程序从 fd 文件描述符中读取32字节到 buf的内存中,并与字符串 LETMEWIN\n 进行比较,若相等则打印 flag 文件的内容,否则失败。

代码读到这里就卡住了,不知道从哪入手。
接下来对题目进行了查询知道字符描述符的概要:每个Unix进程(除了可能的守护进程)应均有三个标准的POSIX文件描述符,对应于三个标准流:

整数值 名称 符号常量 文件流
0 Standard input STDIN_FILENO stdin
1 Standard output STDOUT_FILENO stdout
2 Standard error STDERR_FILENO stderr

在 Linux 系统下,文件描述符 0 , 1 , 2 分别对应系统的标准输入,标准输出,和标准错误输出。
回到上面的代码中,当read函数对文件操作时,当fd为 0 时,我们可以控制标准输入向buf中写入数据。
写一个 demo 来验证自己的想法:

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
char buf[32];
int main(int argc, char* argv[], char* envp[]){
int fd = atoi(argv[1]);
int len = 0;
len = read(fd, buf, 32);
printf(">>>buf:%s",&buf);
printf(">>>len:%s\n",&len);
}

结果为:

能证明想法是对的。
此题可利用标准输入来将字符串 LETMEWIN\n 写到标准输入中,然后使得 fd 变量值为 0 即可从标注输入中读入,就可以得到flag。

collision – 3 pt

1
2
3
4
Daddy told me about cool MD5 hash collision today.
I wanna do something like that too!
ssh col@pwnable.kr -p2222 (pw:guest)

查看当前目录的col.c文件

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;
}

题目描述md5碰撞。而第19行代码中的argv[1]可以知道密码的长度应该是20个字符。

从第三行中的check_password知道代码内将ip强制转化为int指针,而char占用1位,int4位,那么转化后就是5个数组,跟for循环也是吻合的,那么就是说char转化为int后加起来要等于0x21DD09EC 。意思就是说将输入的20个字符拆成5组数据,将5组数据的整型值相加与目标值 0x21DD09EC 进行比较,相等则打印 flag,不等则失败。
此题直接将 0x21DD09EC 拆成5个数字的和即可,1+4的选择,通过 argv[1] 输入时,需要注意使用小端序。

bof – 5 pt

1
2
3
4
5
6
7
Nana told me that buffer overflow is one of the most common software vulnerability.
Is that true?
Download : http://pwnable.kr/bin/bof
Download : http://pwnable.kr/bin/bof.c
Running at : nc pwnable.kr 9000

缓冲区溢出,老早就想了解溢出的东西了。将bof和源码下载下来,使用file查看,是32位的ELF 可执行文件,这种经常是在linux系统下进行调试的。

查看权限没有执行权限,给予相应的权限。

!坚持技术分享,您的支持将鼓励我继续创作!