首页
社区
课程
招聘
5
[原创]pwnable.kr input 分析
发表于: 2020-6-20 20:17 19557

[原创]pwnable.kr input 分析

2020-6-20 20:17
19557

0x00 前言

最近做htb的时候遇到了一个bof的题,但是由于很久之前学过的东西有点想不起,所以就找到了一个pwn的平台的练习。做了几个发现实际难度并不是很大,直到做到这个input的时候,感觉难度一下子就上来了(可能是对于linux理解太菜了,昨天看了一天),所以想进行一下详细的分析,希望可以把这道题所有的知识点都吃透。

 

本篇文章想从目标c语言开始分析,分析对应的汇编,以及到python和c两种语言的poc编写。

0x01 题目环境

1.题目

图片描述

2.目标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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys socket.h="">
#include <arpa inet.h="">
 
int main(int argc, char* argv[], char* envp[]){
    printf("Welcome to pwnable.kr\n");
    printf("Let's see if you know how to give input to program\n");
    printf("Just give me correct inputs then you will get the flag :)\n");
 
    // argv
    if(argc != 100) return 0;
    if(strcmp(argv['A'],"\x00")) return 0;
    if(strcmp(argv['B'],"\x20\x0a\x0d")) return 0;
    printf("Stage 1 clear!\n");   
 
    // stdio
    char buf[4];
    read(0, buf, 4);
    if(memcmp(buf, "\x00\x0a\x00\xff", 4)) return 0;
    read(2, buf, 4);
        if(memcmp(buf, "\x00\x0a\x02\xff", 4)) return 0;
    printf("Stage 2 clear!\n");
 
    // env
    if(strcmp("\xca\xfe\xba\xbe", getenv("\xde\xad\xbe\xef"))) return 0;
    printf("Stage 3 clear!\n");
 
    // file
    FILE* fp = fopen("\x0a", "r");
    if(!fp) return 0;
    if( fread(buf, 4, 1, fp)!=1 ) return 0;
    if( memcmp(buf, "\x00\x00\x00\x00", 4) ) return 0;
    fclose(fp);
    printf("Stage 4 clear!\n");   
 
    // network
    int sd, cd;
    struct sockaddr_in saddr, caddr;
    sd = socket(AF_INET, SOCK_STREAM, 0);
    if(sd == -1){
        printf("socket error, tell admin\n");
        return 0;
    }
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = INADDR_ANY;
    saddr.sin_port = htons( atoi(argv['C']) );
    if(bind(sd, (struct sockaddr*)&saddr, sizeof(saddr)) < 0){
        printf("bind error, use another port\n");
            return 1;
    }
    listen(sd, 1);
    int c = sizeof(struct sockaddr_in);
    cd = accept(sd, (struct sockaddr *)&caddr, (socklen_t*)&c);
    if(cd < 0){
        printf("accept error, tell admin\n");
        return 0;
    }
    if( recv(cd, buf, 4, 0) != 4 ) return 0;
    if(memcmp(buf, "\xde\xad\xbe\xef", 4)) return 0;
    printf("Stage 5 clear!\n");
 
    // here's your flag
    system("/bin/cat flag");   
    return 0;
}
</arpa></sys></string.h></stdlib.h></stdio.h>

0x02 分析正文

发现c中需要满足5个要求,方能得到flag,所以我们也分成5个部分进行分析

1.argv

1.1 目标c语言

1
2
3
4
if(argc != 100) return 0;
if(strcmp(argv['A'],"\x00")) return 0;
if(strcmp(argv['B'],"\x20\x0a\x0d")) return 0;
printf("Stage 1 clear!\n");

这里c语言描述的是需要至少100个参数,并且argv['A']得是\x00
也就是终止符,argv['B']为\x20\x0a\x0d.

1.2 ida对比学习

由于直接写在ida中比较方便也比较清楚,所以就直接标注在ida里了。
图片描述

1.3 python poc

1
2
3
4
5
6
7
8
9
10
11
12
import subprocess
 
#argv
input_path="./input"
argv=[]
argv.append(input_path)
for i in range(1,100):
    argv.append('A')
argv[ord('A')]=""
argv[ord('B')]="\x20\x0a\x0d"
print(argv[ord('B')])
subprocess.Popen(argv)

效果如下:
图片描述

1.4 c语言 poc

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include <unistd.h>
int main(){
    char *argv[101] = {"/root/Desktop/tools/bof/pwnablekr/input/input", [1 ... 99] = "A", NULL};
        argv['A'] = "\x00";
        argv['B'] = "\x20\x0a\x0d";
    char *envp[]={0,NULL};
    execve("/root/Desktop/tools/bof/pwnablekr/input/input",argv,envp);   
}
</unistd.h></stdio.h>

效果如下:
图片描述

2.stdio

2.1 目标c语言

1
2
3
4
5
6
char buf[4];
read(0, buf, 4);
if(memcmp(buf, "\x00\x0a\x00\xff", 4)) return 0;
read(2, buf, 4);
    if(memcmp(buf, "\x00\x0a\x02\xff", 4)) return 0;
printf("Stage 2 clear!\n");

这里作为c语言来说理解还是比较简单的,第一个read,读取标准输入,就是从键盘上获取一个标准输入,第二个read,获取标准错误输出,然后进行对比。真正的难点就是去如何构造这个标准错误输出了,输入还是比较好构造的。

2.2 ida对比学习

图片描述
感觉看了源码之后发现ida看起来也很清楚了

2.3 python poc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import subprocess
import os,sys
#argv
input_path="./input"
argv=[]
argv.append(input_path)
for i in range(1,100):
    argv.append('A')
argv[ord('A')]=""
argv[ord('B')]="\x20\x0a\x0d"
print(argv[ord('B')])
r,w=os.pipe()
r_e,w_e=os.pipe()
os.write(w, "\x00\x0a\x00\xff")
os.write(w_e, "\x00\x0a\x02\xff")
subprocess.Popen(argv,stdin=r,stderr=r_e)

相对于c来说,还是觉的解决问题,python更快一点。
效果:
图片描述

2.4 c语言 poc

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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys socket.h="">
#include <arpa inet.h="">
#include <unistd.h>
int main(){
    char *argv[101] = {"/root/Desktop/tools/bof/pwnablekr/input/input", [1 ... 99] = "A", NULL};
        argv['A'] = "\x00";
        argv['B'] = "\x20\x0a\x0d";
    char *envp[]={0,NULL};
 
 
    int fd_0[2];
    int fd_2[2];
 
    pid_t child;
 
    if (pipe(fd_0)<0||pipe(fd_2)<0)
    {
        perror("error");
    }
 
    write(fd_0[1],"\x00\x0a\x00\xff",4);
    write(fd_0[1],"\x00\x0a\x02\xff",4);
    dup2(fd_0[0],0);
    dup2(fd_0[0],2);
    execve("/root/Desktop/tools/bof/pwnablekr/input/input",argv,envp);           
}
</unistd.h></arpa></sys></string.h></stdlib.h></stdio.h></stdio.h>

效果如下:
图片描述

 

这里还是要说一下的,不然的话就没什么意义了。

 

涉及到知识点:
pipe,linux下的管道问题,这个管道有俩,一个是输入,一个是输出,我们需要做的就是控制这个输出的内容。
根据查到的资料,可以利用先fock一个子进程,在子进程进行输入,然后主进程复制文件流,拿到输出。此时就满足了题目的要求。但是之后发现不需要fock子进程,直接写也是可以的,没什么问题。
最终的实质就是利用pipe构造了标准错误输出。

3.env


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2020-6-21 21:14 被王嘟嘟编辑 ,原因:
上传的附件:
收藏
免费 5
支持
分享
赞赏记录
参与人
雪币
留言
时间
PLEBFE
为你点赞~
2022-7-30 13:47
shinratensei
为你点赞~
2022-7-15 11:41
cease2e
为你点赞~
2021-1-5 19:45
开花的水管
为你点赞~
2020-6-24 15:24
0x指纹
为你点赞~
2020-6-22 09:21
最新回复 (7)
雪    币: 35662
活跃值: (64606)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
2
这题有附件吗?若有,麻烦上传一下
2020-6-21 18:34
0
雪    币: 1110
活跃值: (574)
能力值: ( LV3,RANK:35 )
在线值:
发帖
回帖
粉丝
3
Editor 这题有附件吗?若有,麻烦上传一下
有的,已上传
2020-6-21 21:15
0
雪    币: 1535
活跃值: (695)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
感谢分享~
2020-6-24 15:24
0
雪    币: 22
活跃值: (23)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
想问问楼主题目附件是怎么拿下来的啊,还是说自己把源码弄下来编译呢
2020-11-13 14:13
0
雪    币: 513
活跃值: (2224)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
6
CharesFang 想问问楼主题目附件是怎么拿下来的啊,还是说自己把源码弄下来编译呢[em_23]
scp 能下载下来   scp -P 2222 -r  input2@pwnable.kr:/home/input2 /tmp/input2  密码guest
2021-1-5 14:34
0
雪    币: 22
活跃值: (23)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
Zard_ scp 能下载下来 scp -P 2222 -r input2@pwnable.kr:/home/input2 /tmp/input2 密码guest
感谢大佬啦!
2021-1-19 14:27
0
雪    币: 228
活跃值: (592)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8

<这里原本是一个很傻的问题,现在删除了>

最后于 2021-10-4 21:25 被KSr01dO编辑 ,原因:
2021-9-6 18:04
1
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册