首页
社区
课程
招聘
[原创]手工隐藏api函数调用——简单对付静态分析
发表于: 2009-7-25 15:25 20040

[原创]手工隐藏api函数调用——简单对付静态分析

2009-7-25 15:25
20040

隐藏api函数调用对于对付静态分析,不用说是非常有意义的,许多加壳软件在输入表上大做文章,其中有一个重要的作用就是让破解者在得到的反汇编代码中看不到正常的api函数调用。我做一个最简单的测试,在不借助加壳软件和虚拟机保护技术的情况下,用手写代码的方式来实现隐藏api函数调用。
先看看我要保护的代码:

#include "windows.h"
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
  MessageBox(0,"Reverse Me","Test",0);
  return 0;
}
#include "windows.h"
typedef int (WINAPI *MYFUNC)(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
  char MsgBoxA[]={0x5c,0x74,0x62,0x62,0x70,0x76,0x74,0x53,0x7e,0x69,0x50,0x00};  //字符串"MessageBoxA"的加密形式。
  char lpText[]={0x43,0x74,0x67,0x74,0x63,0x62,0x74,0x31,0x5C,0x74,0x00};  //字符串"Reverse Me"的加密形式。
  char lpCaption[]={0x45,0x74,0x62,0x65,0x00};  //字符串"Test"的加密形式。
  for(int i=0;i<strlen(MsgBoxA);i++)  MsgBoxA[i]^=0x11;  //解密字符串"MessageBoxA"
  for(i=0;i<strlen(lpText);i++)    lpText[i]^=0x11;  //解密字符串"Reverse Me"  
  for(i=0;i<strlen(lpCaption);i++)  lpCaption[i]^=0x11;  //解密字符串"Test"
  HMODULE hMod=LoadLibrary("user32.dll");
  if(hMod)
  {
    MYFUNC func=(MYFUNC)GetProcAddress(hMod,MsgBoxA); //获取MessageBoxA的函数地址。
    func(0,lpText,lpCaption,0);  //调用MessageBoxA函数。
    FreeLibrary(hMod);
  }
  return 0;
}
。。。。。。

  MYFUNC func=NULL;
  char * pFuncName;
  HMODULE hMod=LoadLibrary("user32.dll");
  if(hMod)
  {
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hMod;
    PIMAGE_NT_HEADERS pNtHeader  = (PIMAGE_NT_HEADERS)((ULONG)hMod+pDosHeader->e_lfanew);
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = &(pNtHeader->OptionalHeader);
    PIMAGE_DATA_DIRECTORY pExportData = (PIMAGE_DATA_DIRECTORY)(&(pOptionalHeader->DataDirectory[0]));
    PIMAGE_EXPORT_DIRECTORY pExportTable = (PIMAGE_EXPORT_DIRECTORY)((ULONG)hMod+pExportData->VirtualAddress);
    ULONG * AddrFunctions=(ULONG *)((ULONG)hMod+pExportTable->AddressOfFunctions);
    ULONG * AddrNames=(ULONG *)((ULONG)hMod+pExportTable->AddressOfNames);
    for(i=0;i<pExportTable->NumberOfFunctions;i++)
    {
      pFuncName=(char *)((LONG)hMod+AddrNames[i]);
      if(strcmp(pFuncName,MsgBoxA)==0)
      {
        func=(MYFUNC)((LONG)hMod+AddrFunctions[i]);
        break;
      }
    }
    if(func)
      func(0,lpText,lpCaption,0);
    FreeLibrary(hMod);
  }
。。。。。。
#pragma comment(linker, "/SECTION:.text,ERW")
void Decrypt(char * start,char * end)
{  
  for(char * i=start;i<end;i++)
  {
    (*i)^=0x11;
  }
}
。。。。。。

  Decrypt((char * )401000,(char * )400000); //两个需要更正的地址参数。
  __asm inc eax  __asm dec eax  //16进制对应40 48 ,用来标记加密代码段起始地址
  HMODULE hMod=LoadLibrary("user32.dll");
。。。。。。

  __asm inc eax __asm dec eax //16进制对应40 48,用来标记加密代码段末地址
  return 0;
。。。。。。

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

上传的附件:
收藏
免费 7
支持
分享
最新回复 (38)
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
你这样没用的, 我相信没有任何人会只用 IDA 看程序的 ,动静合一 就连 几百年前的武术都知道这个道理
人家 一个 f9 就可以看到不该看的地方
2009-7-25 19:31
0
雪    币: 709
活跃值: (2420)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
3
心得写的很好.
谢谢分享~~~
2009-7-25 23:06
0
雪    币: 129
活跃值: (1095)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
用COM接口技术会好些的,可以给反汇编增加难度。
2009-7-25 23:09
0
雪    币: 227
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
如果到了最后还是完整的解密的话 那么用OD运行之后不就全都看到了吗?
2009-7-26 01:30
0
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
6
加密后就不信你不解密,在你解密的时候我再K你
2009-7-26 09:59
0
雪    币: 97
活跃值: (30)
能力值: ( LV2,RANK:140 )
在线值:
发帖
回帖
粉丝
7
呵呵,我这个旨在对付静态分析.那个SMC没有嵌套,也没有Anti-Debug,要对付它,那比捏死一只蚂蚁还容易.
2009-7-26 17:48
0
雪    币: 107
活跃值: (404)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
对初学者应当很受用
2009-7-28 09:50
0
雪    币: 263
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
思想重要,思想重要~
2009-7-28 10:46
0
雪    币: 381
活跃值: (140)
能力值: ( LV13,RANK:330 )
在线值:
发帖
回帖
粉丝
10
这种隐藏方式以前也用汇编实现过,对静态的还算有点效果,可拿OD一跟进去,或用API监视工具,最后还是会暴露无疑的。即使自己弄个该功能的引擎,其效果还不如拿VMProtect之类的加壳工具搞定了事,总之个人认为效果不是很好,没有深究的念头
2009-7-28 11:07
0
雪    币: 101
活跃值: (88)
能力值: ( LV2,RANK:140 )
在线值:
发帖
回帖
粉丝
11
牛~~~~~~~
2009-7-28 11:16
0
雪    币: 222
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
学习了
还用 scm 呀
不错
2009-7-28 11:30
0
雪    币: 388
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
13
学习  想法很好
2009-7-28 17:25
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
谢谢,学习了,但是这种方法,如果软件稍微大一点会不会影响运行速度,而且编程复杂度也很高!
2009-7-28 19:55
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
这样感觉编程好复杂了啊。本来API编程就是隐藏底层代码的。这样的话,写代码就累死了。。。。。
2009-7-28 20:19
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
学习一下,支持了!
2009-7-28 22:18
0
雪    币: 200
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
非常感谢贡献
2009-7-28 22:38
0
雪    币: 1450
活跃值: (35)
能力值: (RANK:680 )
在线值:
发帖
回帖
粉丝
18
现在很多病毒都是这么干的, 虽然IDA看不到API调用过程, 但是如果比较有规律的话, 可以写idc来处理.
你这里因为程序较简单, 是将地址表放在局部变量内. 一般病毒要用到很多API, 一般地址表实在全局变量.
所以调用时, 大多类似一下方式:

mov R, [0040XXXX]
... ... //无关指令
...
call R

像这种就很有规律, 可以用idc处理.
2009-7-28 23:24
0
雪    币: 1450
活跃值: (35)
能力值: (RANK:680 )
在线值:
发帖
回帖
粉丝
19
另外, 通过比较函数名Hash而不是函数名字串可以更节省代码空间, 也更优美.
2009-7-28 23:26
0
雪    币: 208
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
如果你把要隐藏的函数的hash算出来,硬编码到程序中,查找API名字的时候,通过比较API函数名的hash值,这样是不是会增加一些调试的难度?
2009-7-29 09:53
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
写的真不错。很好
2009-7-29 11:48
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
学习了,谢谢分享。
2009-7-29 14:45
0
雪    币: 1657
活跃值: (291)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
23
不是我说LZ,你这个基本作用不大,隐藏的API只要留意一下就能看出来,前提是熟悉API啊,因为常规的一些API,看习惯了,很容易根据参数就能一眼看出来,是那个API,即使看不出来,也能知道API是那类的,如果调试的话,你那个没作用,姑且不说能不能调试,就算不能调试,这样的也可以根据整体代码的流程来看出来,比如:前面都注册窗口了,下面的个函数被LZ隐藏了,但是习惯性的就知道下面一个函数是创建窗口,在根据参数一看,几乎98%确定,我基本上拿OD看汇编,IDA只看流程,所以,LZ的方法,基本上作用不大,再说了,就算拿IDA看,IDA只是相关的参考,仔细分析一下,还是可以发现被隐藏的。

再说了,LZ这个思路到是不错的,但是,这样做如果真一个个去隐藏,确实很麻烦,而又耗时。
2009-7-29 15:20
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
学习了,呵呵
2009-7-29 23:44
0
雪    币: 463
活跃值: (116)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
都不看标题的..

人家说是简单对付静态分析.,不用IDA,难道还有比IDA更强的分析工具?

用OD的人都买块砖头拍自己头吧.
2009-8-1 11:20
0
游客
登录 | 注册 方可回帖
返回
//