以下是我开发过程中所遇到的一些问题,分享下初学者就少碰下壁。
1. 不要用 *1.02 这种浮点算法,会死在这种命令上,那个2B2040绝对会出错,所以尽量别用了。
000300B3 DF6D D8 FILD QWORD PTR SS:[EBP-28]
000300B6 DC0D 40202B00 FMUL QWORD PTR DS:[2B2040]
000300BC D97D D6 FSTCW WORD PTR SS:[EBP-2A]
2. 当我们使用花指令或者在shellcode某些位置存放大量数据时,我们可以使用如下方式
__asm{
__emit 0xff
__emit 0xfe
__emit 0xff
.}
3. 地址重定位。当我们使用createthread函数时,其中回调地址必须为内存中的绝对地址,这时候我们就必须计算出回调函数的绝对地址了。
//记得-8 DWORD GetEip()
{
__asm{
call get_eip
get_eip:
pop eax
}
}void WINAPI AdjustFunction(struct ADJUSTFUNCTIONS* pFuns)
{
DWORD dwGetEip;
dwGetEip = GetEip();
dwGetEip -= 8; //计算得到 GetEip()函数在内存中的地址
pFuns->lpThreadProc = (DWORD)dwGetEip+( (DWORD)ThreadProc- (DWORD)GetEip ); // 以GetEip()函数做参考动态计算出其他 函数的地址
}
// 调用的时候这样写
hThread = modules.kernel32.CreateThread(NULL,0,adjustFuns.lpThreadProc,¶m,0,NULL); 4. pMem->uSum = memState.ullTotalPhys/1024/1024; 这种 ULONGLONG做除法会调用 9:41 AM 4/15/2017
call _aulldiv (132ABC0h) 所以会出问题,因为这个函数不在我们控制之内。当直接注入到其他进程时就会崩溃。
vs10 调试命中断点后Alt+8打开反汇编窗口,如下所示
pMem->uSum = memState.ullTotalPhys/1024/1024;
01212324 6A 00 push 0
01212326 68 00 04 00 00 push 400h
0121232B 8B 45 C4 mov eax,dword ptr [ebp-3Ch]
0121232E 50 push eax
0121232F 8B 4D C0 mov ecx,dword ptr [ebp-40h]
01212332 51 push ecx
01212333 E8 88 88 11 00 call _aulldiv (132ABC0h)
01212338 6A 00 push 0
0121233A 68 00 04 00 00 push 400h
0121233F 52 push edx
01212340 50 push eax
01212341 E8 7A 88 11 00 call _aulldiv (132ABC0h)
01212346 8B 4D 08 mov ecx,dword ptr [pMem]
01212349 89 41 08 mov dword ptr [ecx+8],eax
0121234C 89 51 0C mov dword ptr [ecx+0Ch],edx 后来打算使用 pMem->uSum = memState.ullTotalPhys>>20; 作为替换方案。看看反汇编就知道不行了 : 下面这条就是个问题。避免的办法 就是不做除法了,或者自己去实现大数据的除法或者移动。
_aullshr (931F40h) pMem->uSum = memState.ullTotalPhys>>20;
00812324 8B 45 C0 mov eax,dword ptr [ebp-40h]
00812327 8B 55 C4 mov edx,dword ptr [ebp-3Ch]
0081232A B1 14 mov cl,14h
0081232C E8 0F FC 11 00 call _aullshr (931F40h)
00812331 8B 4D 08 mov ecx,dword ptr [pMem]
00812334 89 41 08 mov dword ptr [ecx+8],eax
00812337 89 51 0C mov dword ptr [ecx+0Ch],edx 5. switch case 。最近开发发现使用swich也会出现问题,代码就不看了,如果发现代码注入运行时,有问题不妨看看是不是switch的问题。(这几天调试发现多个case的swich会出现 [ecx*4+0x04xxxxx]的计算,其中0x4xxxx是个绝对地址,绝B会出问题。(9:48 AM 4/15/2017)
6. shellcode如何存放全局变量,我们知道我们的shellcode从入口进入,最后推出,所有数据的传递都考参数,这样就有很多不变,我举个例子,每个函数的实现都离不开WINAPI,我们首先获取所需的API放在一个结构中,每个函数的使用都必须传递这么一个结构,这就给开发带来了很多不变,也增加了代码量。如果存放在全局变量里,并且我们还能获得到这个变量位置,那么函数调用就不必传入这个结构体指针了。例如下面,这是我自己实现的获取内存使用状态的函数;其中x_GetModules()就可以从全局变量中获取pMod信息;我们知道一个进程只有一个进程结构贴PEB,并且每个线程也能获取PEB,并且PEB获取很简单,所以可以在PEB上做文章,我们可以在不常用的字段上存放我们的全局变量地址,这样目的就达到了 (10:15 AM 4/15/2017) 这里我就不分享我具体的细节了。
EXPORTAPI void x_GetMemoryInfo(PMEMORYINFO pMem)
{
MEMORYSTATUSEX memState;
PMODULES pMod;
pMod = x_GetModules();
memState.dwLength = sizeof(MEMORYSTATUSEX);
pMod->kernel32.GlobalMemoryStatusEx(&memState);
pMem->uSum = memState.ullTotalPhys;
pMem->uFree = memState.ullAvailPhys;
}
EXPORTAPI PMODULES x_GetModules()
{
return &( x_GetGlobalData()->modules );
} 这篇帖子作为长期维护贴,不定期加入新东西
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!