http://tech.acnow.net/Html/Program/VC/VCShell/
原文是安全中国的yellow写的“深入剖析ShellCode”云云,在上面的地址可以找到,
但文中给出的例子不是无法编译,就是编译过后无法按想法执行,我将代码改变如下,可以执行,供大家参考。
__inline __declspec(naked) unsigned int __stdcall GetKernel32()
{
__asm
{
push esi
push ecx
mov esi,fs:0
lodsd
GetExeceptionFilter:
cmp [eax],0xffffffff
je GetedExeceptionFilter //如果到达最后一个节点(它的pfnHandler指向UnhandledExceptionFilter)
mov eax,[eax] //否则往后遍历,一直到最后一个节点
jmp GetExeceptionFilter
GetedExeceptionFilter:
mov eax, [eax+4]
FindMZ:
and eax,0xffff0000 //根据PE执行文件以64k对界的特征加快查找速度
cmp word ptr [eax],'ZM' //根据PE可执行文件特征查找KERNEL32.DLL的基址
jne MoveUp //如果当前地址不符全MZ头部特征,则向上查找
mov ecx,[eax+0x3c]
add ecx,eax
cmp word ptr [ecx],'EP' //根据PE可执行文件特征查找KERNEL32.DLL的基址
je Found //如果符合MZ及PE头部特征,则认为已经找到,并通过Eax返回给调用者
MoveUp:
dec eax //准备指向下一个界起始地址
jmp FindMZ
Found:
pop ecx
pop esi
ret
}
}
__inline __int32 __cdecl GetFunctionByName(__int32 ImageBase,const char*FuncName,int flen)
{
unsigned int FunNameArray,PE, Count=0,IED,iedN;
__asm
{
mov eax,ImageBase
add eax,0x3c //指向PE头部偏移值e_lfanew
mov eax,[eax] //取得e_lfanew值
add eax,ImageBase //指向PE header
cmp [eax],0x00004550
jne NotFound //如果ImageBase句柄有错
mov PE,eax
mov eax,[eax+0x78]
add eax,ImageBase
mov IED,eax //指向IMAGE_EXPORT_DIRECTORY
mov eax,[eax+0x0c]
add eax,ImageBase //指向引出模块名,如果在查找KERNEL32.DLL的引出函数那么它将指向"KERNEL32.dll"
mov iedN,eax
mov eax,IED
mov eax,[eax+0x20]
add eax,ImageBase
mov FunNameArray,eax //保存函数名称指针数组的指针值
mov ecx,IED
mov ecx,[ecx+0x14] //根据引出函数个数NumberOfFunctions设置最大查找次数
FindLoop:
mov eax,[eax]
add eax,ImageBase
mov esi,FuncName
mov edi,eax
push ecx
mov ecx,flen //逐个字符比较,如果相同则为找到函数,注意这里的ecx值
cld
rep cmpsb
jne FindNext //如果当前函数不是指定的函数则查找下一个
add esp,4 //如果查找成功,则清除用于控制外层循环而压入的Ecx,准备返回
mov eax,IED
mov eax,[eax+0x24]
add eax,ImageBase
shl Count,1 //根据AddressOfName计算索引,然后根据此索引查AddressOfNameOrdinals同样索引下的序号,再根据此序号为索引查AddressOfFunctions数组得到待求函数的地址。 add eax,Count
mov eax,[eax]
and eax,0x0000ffff
mov ebx,eax
mov eax,IED
mov eax,[eax+0x1c]
add eax,ImageBase
shl ebx,2
mov eax,[eax+ebx]
add eax,ImageBase
jmp Found
FindNext:
inc Count //记录函数索引
add FunNameArray,4
mov eax,FunNameArray //下一个函数名指针
pop ecx //恢复压入的ecx(NumberOfFunctions),进行计数循环
loop FindLoop //如果ecx不为0则递减并回到FindLoop,往后查找
NotFound:
xor eax,eax //如果没有找到,则返回0
Found:
}
}void main()
{
__int32 loadlibfun;
char title[]="test",user32[]="user32",msgf[]="MessageBoxA";
char fn1[]="LoadLibraryA";
char fn2[]="MessageBoxA";
loadlibfun=GetFunctionByName(GetKernel32(),fn1,12);
__asm
{
lea eax,user32
push eax
call dword ptr loadlibfun //相当于执行LoadLibrary("user32"); lea ebx,msgf
push 0x0b //"MessageBoxA"的长度
push ebx
push eax call GetFunctionByName mov ebx,eax
add esp,0x0c //GetFunctionByName使用C调用约定,由调用者调整堆栈
push 0
lea eax,title
push eax
push eax
push 0
call ebx //相当于执行MessageBox(NULL,"test","test",MB_OK)
}
}有没有哪位,能把顶上的连接中yellow的最后一个例子解释一下!
我只改了前面的例子,后面的看不懂!
原文是安全中国的yellow写的“深入剖析ShellCode”云云,在上面的地址可以找到,
但文中给出的例子不是无法编译,就是编译过后无法按想法执行,我将代码改变如下,可以执行,供大家参考。
__inline __declspec(naked) unsigned int __stdcall GetKernel32()
{
__asm
{
push esi
push ecx
mov esi,fs:0
lodsd
GetExeceptionFilter:
cmp [eax],0xffffffff
je GetedExeceptionFilter //如果到达最后一个节点(它的pfnHandler指向UnhandledExceptionFilter)
mov eax,[eax] //否则往后遍历,一直到最后一个节点
jmp GetExeceptionFilter
GetedExeceptionFilter:
mov eax, [eax+4]
FindMZ:
and eax,0xffff0000 //根据PE执行文件以64k对界的特征加快查找速度
cmp word ptr [eax],'ZM' //根据PE可执行文件特征查找KERNEL32.DLL的基址
jne MoveUp //如果当前地址不符全MZ头部特征,则向上查找
mov ecx,[eax+0x3c]
add ecx,eax
cmp word ptr [ecx],'EP' //根据PE可执行文件特征查找KERNEL32.DLL的基址
je Found //如果符合MZ及PE头部特征,则认为已经找到,并通过Eax返回给调用者
MoveUp:
dec eax //准备指向下一个界起始地址
jmp FindMZ
Found:
pop ecx
pop esi
ret
}
}
__inline __int32 __cdecl GetFunctionByName(__int32 ImageBase,const char*FuncName,int flen)
{
unsigned int FunNameArray,PE, Count=0,IED,iedN;
__asm
{
mov eax,ImageBase
add eax,0x3c //指向PE头部偏移值e_lfanew
mov eax,[eax] //取得e_lfanew值
add eax,ImageBase //指向PE header
cmp [eax],0x00004550
jne NotFound //如果ImageBase句柄有错
mov PE,eax
mov eax,[eax+0x78]
add eax,ImageBase
mov IED,eax //指向IMAGE_EXPORT_DIRECTORY
mov eax,[eax+0x0c]
add eax,ImageBase //指向引出模块名,如果在查找KERNEL32.DLL的引出函数那么它将指向"KERNEL32.dll"
mov iedN,eax
mov eax,IED
mov eax,[eax+0x20]
add eax,ImageBase
mov FunNameArray,eax //保存函数名称指针数组的指针值
mov ecx,IED
mov ecx,[ecx+0x14] //根据引出函数个数NumberOfFunctions设置最大查找次数
FindLoop:
mov eax,[eax]
add eax,ImageBase
mov esi,FuncName
mov edi,eax
push ecx
mov ecx,flen //逐个字符比较,如果相同则为找到函数,注意这里的ecx值
cld
rep cmpsb
jne FindNext //如果当前函数不是指定的函数则查找下一个
add esp,4 //如果查找成功,则清除用于控制外层循环而压入的Ecx,准备返回
mov eax,IED
mov eax,[eax+0x24]
add eax,ImageBase
shl Count,1 //根据AddressOfName计算索引,然后根据此索引查AddressOfNameOrdinals同样索引下的序号,再根据此序号为索引查AddressOfFunctions数组得到待求函数的地址。 add eax,Count
mov eax,[eax]
and eax,0x0000ffff
mov ebx,eax
mov eax,IED
mov eax,[eax+0x1c]
add eax,ImageBase
shl ebx,2
mov eax,[eax+ebx]
add eax,ImageBase
jmp Found
FindNext:
inc Count //记录函数索引
add FunNameArray,4
mov eax,FunNameArray //下一个函数名指针
pop ecx //恢复压入的ecx(NumberOfFunctions),进行计数循环
loop FindLoop //如果ecx不为0则递减并回到FindLoop,往后查找
NotFound:
xor eax,eax //如果没有找到,则返回0
Found:
}
}void main()
{
__int32 loadlibfun;
char title[]="test",user32[]="user32",msgf[]="MessageBoxA";
char fn1[]="LoadLibraryA";
char fn2[]="MessageBoxA";
loadlibfun=GetFunctionByName(GetKernel32(),fn1,12);
__asm
{
lea eax,user32
push eax
call dword ptr loadlibfun //相当于执行LoadLibrary("user32"); lea ebx,msgf
push 0x0b //"MessageBoxA"的长度
push ebx
push eax call GetFunctionByName mov ebx,eax
add esp,0x0c //GetFunctionByName使用C调用约定,由调用者调整堆栈
push 0
lea eax,title
push eax
push eax
push 0
call ebx //相当于执行MessageBox(NULL,"test","test",MB_OK)
}
}有没有哪位,能把顶上的连接中yellow的最后一个例子解释一下!
我只改了前面的例子,后面的看不懂!
XP下可以运行
----------------------------------------------------
弹出了“test”对话框了!
真的吗?
我正在看一偏帖子讲如何绕过IE的运行activeX的警告。如果成功,我再帖出来,希望再帮忙看看。