重新写一个小execve的外壳code [英] Re-writing a small execve shellcode

查看:203
本文介绍了重新写一个小execve的外壳code的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过的http://hackoftheday.securitytube.net/2013/04/demystifying-execve-shell$c$c-stack.html

我明白了NASM程序,它调用的execve ,并试图重新写了。

I understood the nasm program which invokes execve and was trying to re-write it.

一些背景资料:

int execve(const char *filename, char *const argv[], char *const envp[]);

因此​​, EAX = 11 (用于功能呼叫数的execve ), EBX 应指向的char *文件名 ECX 应指向的argv [] (这将是相同的 EBX 以来的第一个参数是 *文件名本身如/ bin / sh的,在这种情况下),而 EDX 将指向 envp [] 在这种情况下)。

So, eax = 11 (function call number for execve), ebx should point to char* filename, ecx should point to argv[] (which will be the same as ebx since the first argument is the *filename itself e.g. "/bin/sh" in this case), and edx will point to envp[] (null in this case).

原NASM code:

Original nasm code:

global _start

section .text
_start:

xor eax, eax
push eax

; PUSH //bin/sh in reverse i.e. hs/nib//

push 0x68732f6e
push 0x69622f2f

mov ebx, esp

push eax
mov edx, esp

push ebx
mov ecx, esp

mov al, 11
int 0x80

堆栈是如下:

现在我试图通过减少一些指令来优化它。我同意,直到 MOV EBX,ESP 的code将保持不变。然而,由于 ECX 将需要指向 EBX ,我可以重新写入code如下:

Now i tried to optimize this by reducing a few instructions. I agree that till mov ebx, esp the code will remain the same. However, since ecx will need to point to ebx, I can re-write the code as follows:

global _start

section .text
_start:

xor eax, eax
push eax

; PUSH //bin/sh in reverse i.e. hs/nib//

push 0x68732f6e
push 0x69622f2f
mov ebx, esp

mov ecx,ebx

push eax
mov edx, esp

mov al, 11
int 0x80

不过,我得到一个分段错误,当我跑我重新编写code。

However, I get a segmentation fault when I run my re-written code.

我的堆栈如下:

My stack is as follows:

任何想法,为什么重新写code不起作用?我的地址值是按照我的想法跑了GDB还和,但它只是将无法运行。

Any ideas why the re-written code does not work? I've ran gdb also and the address values are according to my thinking, but it just won't run.

推荐答案

在这两种情况下EBX指向字符串// bin / sh的。 C $ C $的C这样的等价的:

In both cases ebx is pointing to the string "//bin/sh". The equivalent of C code like this:

char *EBX = "//bin/sh";  

但是,在第一个例子中,ECX设定为指针,字符串的地址。 C $ C $的C这样的等价的:

But in your first example, ecx is set to the address of a pointer to that string. The equivalent of C code like this:

char *temp = "//bin/sh"; // push ebx
char **ECX = &temp;      // mov ecx, esp

而在第二个例子中,ECX正好被设置为相同的值作为EBX

While in your second example, ecx is just set to the same value as ebx.

char *ECX = "//bin/sh";

这两个例子是从根本上的不同,与ECX有两种完全不同类型的和值。

The two examples are thus fundamentally different, with ecx have two completely different types and values.

更新:

我要补充一点,在技术上ECX是字符指针数组(中的的argv 的说法),而不是仅仅指向一个字符指针。实际上,你正在构建堆栈上两个项目数组。

I should add that technically ecx is an array of char pointers (the argv argument), not just a pointer to a char pointer. You're actually building up a two item array on the stack.

char *argv[2];
argv[1] = NULL;         // push eax, eax being zero
argv[0] = "//bin/sh";   // push ebx
ECX = argv;             // mov ecx,esp

这只是阵列中有一半是加倍的的 envp 的说法了。由于的 envp 的是单个项目阵列与单个项目被设置为NULL,你能想到的的 envp 的参数被设置为C code是这样的:

It's just that half of that array is doubling as the envp argument too. Since envp is a single item array with that single item being set to NULL, you can think of the envp arguments being set with C code like this:

EDX = envp = &argv[1];           

这是通过设置EDX到ESP,而argv数组中只有一半实现建造。结合code两个任务一起,你得到这个:

This is achieved by setting edx to esp while the argv array is only half constructed. Combining the code for the two assignments together you get this:

char *argv[2];
argv[1] = NULL;         // push eax, eax being zero
EDX = &argv[1];         // mov edx,esp
argv[0] = "//bin/sh";   // push ebx
ECX = argv;             // mov ecx,esp

这是一个有点令人费解,但我希望是有道理的给你。

It's a bit convoluted, but I hope that makes sense to you.

更新2

所有的参数的execve 作为寄存器传递,但这些寄存器指向的内存需要被分配的地方 - 在这种情况下,在栈上。由于堆栈在内存中建立朝下,需要以相反的顺序将建造的内存块。

All of the arguments to execve are passed as registers, but those registers are pointers to memory which needs to be allocated somewhere - in this case, on the stack. Since the stack builds downwards in memory, the chunks of memory need to be constructed in reverse order.

三个参数的记忆是这样的:

The memory for the three arguments looks like this:

char *filename:  2f 2f 62 69 | 6e 2f 73 68 | 00 00 00 00 
char *argv[]:    filename    | 00 00 00 00               
char *envp[]:    00 00 00 00   

文件名的构造是这样的:

push eax        // '\0' terminator plus some extra
push 0x68732f6e // 'h','s','/','n'
push 0x69622f2f // 'i','b','/','/'

的argv 的说法是这样的:

push eax // NULL pointer
push ebx // filename

以及 envp 的说法是这样的:

push eax // NULL pointer

但正如我所说,最初的例子决定分享的argv和执行副总裁的记忆,所以没有必要,去年推EAX

我还应该注意到,在构建串时使用的两种双字中的字符的相反顺序是因为机器的字节顺序,而不是堆叠方向

I should also note that the reverse order of the characters in the two dwords used when constructing the string is because of the endianess of the machine, not the stack direction.

这篇关于重新写一个小execve的外壳code的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆