首页
社区
课程
招聘
[原创][shellcode框架(四)] shellcode编程小技巧
发表于: 2017-3-27 14:33 8137

[原创][shellcode框架(四)] shellcode编程小技巧

2017-3-27 14:33
8137

    以下是我开发过程中所遇到的一些问题,分享下初学者就少碰下壁。



 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,&param,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 );	
}

这篇帖子作为长期维护贴,不定期加入新东西


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 938
活跃值: (948)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
坐等楼主更新奇技淫巧
2017-3-27 14:53
0
雪    币: 1140
活跃值: (4217)
能力值: ( LV5,RANK:69 )
在线值:
发帖
回帖
粉丝
3
牛逼   
先收藏
2017-4-6 11:47
0
雪    币: 3738
活跃值: (3872)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
我遇见一个坑,初始化一个结构体为0时,编译器会生成call memset,这样也会崩。
2018-9-6 11:21
0
游客
登录 | 注册 方可回帖
返回
//