首页
社区
课程
招聘
[旧帖] [求助]对于隐藏的函数,OD如何下断点? 0.00雪花
发表于: 2012-3-14 18:49 1450

[旧帖] [求助]对于隐藏的函数,OD如何下断点? 0.00雪花

2012-3-14 18:49
1450
代码隐藏技术在反调试中作用很大。
     有些对话框是调用MessageBox函数显示的,但你用MessageBox下断确拦不住,因为程序将MessageBox函数代码搬到其他的地址空间执行了。具体的原理,kanxue上有一段代码就是一个很好的例子。
    这段原理是读取系统DLL到分配的内存里面去,然后定位到相关的API的代码。对原来的系统API函数下断点将无效。

#include <windows.h>  

char Caption[]="Test";  
char Text[]="MessageBoxA";  

FARPROC  GetApiAddr(DWORD Base,DWORD Api)  
{  
  DWORD VirtualSize;  
  DWORD PhysicalAddr;  
  DWORD RawSize;   
  FARPROC RET=NULL;  
//下面是相关的PE结构部分  
  PIMAGE_DOS_HEADER DosHeader=(PIMAGE_DOS_HEADER)Base;  
  PIMAGE_NT_HEADERS NtHeader=(PIMAGE_NT_HEADERS)((DWORD)DosHeader+(DWORD)DosHeader->e_lfanew);   
  PIMAGE_SECTION_HEADER SecHeader=(PIMAGE_SECTION_HEADER)((DWORD)NtHeader+sizeof(IMAGE_FILE_HEADER)+   
    NtHeader->FileHeader.SizeOfOptionalHeader+4);  
  DWORD SecSum=NtHeader->FileHeader.NumberOfSections;  
  while(SecSum)   
  {  
    PhysicalAddr=(DWORD)SecHeader->Misc.PhysicalAddress;  
    VirtualSize=(DWORD)SecHeader->VirtualAddress;//>Misc.VirtualSize;  
    PhysicalAddr+=VirtualSize;  
    if(Api>=VirtualSize&&Api<=PhysicalAddr)  
    {  
      //这里进行了文件偏移和内存偏移的转换  
      RawSize=SecHeader->PointerToRawData;      
      RawSize-=VirtualSize;  
      Base+=RawSize;  
      Base+=Api;  
    }  
    SecHeader++;  
    SecSum--;  
  }  
  RET=(FARPROC)Base;  
  return RET;  
}  

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)  
{  
  DWORD dwRead;  
  char SystemPath[MAX_PATH]={0};  
  HMODULE hMod=GetModuleHandleA("USER32.DLL");  
  if(!hMod)  
    hMod=LoadLibraryA("USER32.DLL");  
  GetSystemDirectoryA(SystemPath,MAX_PATH);  
  lstrcat(SystemPath,"\\user32.dll");  
  HANDLE Handle=CreateFileA(SystemPath,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);  
  DWORD Size=GetFileSize(Handle,NULL);  
  LPVOID Virtual=VirtualAlloc(NULL,Size,MEM_COMMIT,PAGE_READWRITE);  
  VirtualLock(Virtual,Size);  
  ReadFile(Handle,Virtual,Size,&dwRead,NULL);  //读取到内存中,整个读入,文件偏移保持不变。  
  DWORD MeAddr=(DWORD)GetProcAddress(hMod,"MessageBoxA");  
  MeAddr=MeAddr-(DWORD)hMod; //函数地址相对模块基址偏移量  
  DWORD Virtual1=(DWORD)Virtual;  //分配的内存基址  
  DWORD Api=(DWORD)GetApiAddr(Virtual1,MeAddr);  
  //DWORD Api=(DWORD)GetProcAddress((HMODULE)Virtual1,"MessageBox"); //测试还能否发现MessageBox,发现读取整个dll到内存中后无法搜索到MessageBox了,只能通过地址来搜索。  
_asm{  
    push 0  
    lea eax,Caption  
    push eax  
    lea eax,Text  
    push eax  
    push 0  
    call Api  
  }  
  return FALSE;  
}

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 817
活跃值: (2063)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
楼主可以试一下A-PDF系列软件,每一个软件里面对大多数的API调用都进行了你所说的那种隐藏,但是,却很好找到,例如,它所有变形的API调用的指令都是:

    CALL  401860

    使用OD的搜索所有命令功能,寻找指令:“CALL 401860”至少可以找到60个,这个时候再下断点还用专门去找吗。

    如果能脱A-PDF系列软件的壳,那就说明你的功夫达到了相当高的水准。
2012-3-14 21:32
0
雪    币: 1121
活跃值: (652)
能力值: ( LV5,RANK:66 )
在线值:
发帖
回帖
粉丝
3
楼主你都知道他会读取DLL代码,然后再跳到读出来的代码处,你直接在读取之前下断,不就结了。或者在MessageBox的代码处下内存读取断点,然后再单步。别死脑筋非得在MessageBox的代码上下断。如果是读取文件获得代码,那你就在相应的代码处下条件断点。如果软件是用到了读取,用完了清空,我想没有万能的方法能直接下断点。
2012-3-15 11:45
0
游客
登录 | 注册 方可回帖
返回
//