好友
阅读权限20
听众
最后登录1970-1-1
|
上次发了一个http://www.52pojie.cn/thread-559945-1-1.html,感觉没什么人愿意看代码。
直接封装了一个隐藏输入表功能的命令行工具。
对免杀应该有点用。
这个工具在存在TLS Callbacks函数应该是不能正常工作,因为tls回调函数在entry point之前执行,API调用由于导入表还未初始化会导致失败。
(应该可以把重建输入表的函数注册成一个TLS回调函数解决这个问题,但是我懒,因为大部分程序应该都没有TLS回调函数的)
用法很简单:
输入:
final.exe notepad.exe no.exe
notepad.exe这个是我们要隐藏输入表的文件,
no.exe:这个是我们隐藏后的文件。
隐藏后输入表里只有两个导入函数,如下:
简单测试了几个程序,完美运行。有bug的话,可以跟我说下。
核心代码:
//我使用fun函数来替代大部分汇编代码(少部分还是要自己写的)
//此函数在final中不会调用到,但是这个函数编译后的代码会写入要隐藏输入表的文件中。不知道你们理不理解。
void fun(DWORD LoadLib,DWORD GetAddr,DWORD IID,DWORD base){
LoadLib+=base;
GetAddr+=base;
IID+=base;
LoadLib=*((DWORD*)LoadLib);
GetAddr=*((DWORD*)GetAddr);
PIMAGE_IMPORT_DESCRIPTOR pIID=(PIMAGE_IMPORT_DESCRIPTOR)IID;
while (pIID->OriginalFirstThunk!=NULL){
DWORD vaDLL=pIID->Name+base; //"Kernel32.dll"字符串地址
DWORD hDLL=(*(DWORD _stdcall(*)(DWORD))LoadLib)(vaDLL);
PIMAGE_THUNK_DATA32 vaINT=(PIMAGE_THUNK_DATA32)(pIID->OriginalFirstThunk+base);
PIMAGE_THUNK_DATA32 vaIAT=(PIMAGE_THUNK_DATA32)(pIID->FirstThunk+base);
while (vaINT->u1.AddressOfData!=0){
DWORD vaFun;
if (vaINT->u1.Ordinal&0x80000000){
vaFun=vaINT->u1.Ordinal&0xff;
}else{
vaFun=vaINT->u1.AddressOfData+base+2; //2个字节的Odinals
}
vaIAT->u1.AddressOfData=(*(DWORD _stdcall(*)(DWORD,DWORD))(GetAddr))(hDLL,vaFun);
vaIAT++;
vaINT++;
}
pIID++;
}
return ;
}
int CPE32::IIDHide(){
static char *szItem[3]={"Kernel32.dll","LoadLibraryA","GetProcAddress"};
DWORD rvaIID;
IIDConstruct(szItem,3,&rvaIID);
PIMAGE_IMPORT_DESCRIPTOR pIIDK32=(PIMAGE_IMPORT_DESCRIPTOR)RVA2PBYTE(rvaIID);
//修改导入表指针
DWORD rvaOldImpTable=m_pINH->OptionalHeader.DataDirectory[1].VirtualAddress;
IMAGE_DATA_DIRECTORY ImportTable;
ImportTable.VirtualAddress=PBYTE2RVA((PBYTE)pIIDK32);
ImportTable.Size=0x100;
m_pINH->OptionalHeader.DataDirectory[1]=ImportTable;
InitMemberValue();
//添加代码初始化
DWORD rvaLoadLibrary; IIDGetFunAddrPtr(szItem[1],&rvaLoadLibrary);
DWORD rvaGetProcAddr; IIDGetFunAddrPtr(szItem[2],&rvaGetProcAddr);
DWORD base=m_pINH->OptionalHeader.ImageBase;
// DWORD base=m_
BYTE Code[1000];
PBYTE p=Code;
*p++=0x60; //pushad
*p++=0x68;*((DWORD*)p)=base;p+=4; //push {base}
*p++=0x68;*((DWORD*)p)=rvaOldImpTable;p+=4; //push {OldImportTa}
*p++=0x68;*((DWORD*)p)=rvaGetProcAddr;p+=4; //push {GetProcAddr}
*p++=0x68;*((DWORD*)p)=rvaLoadLibrary;p+=4; //push {LoadLibrary}
*p++=0x50; //push eax;{这里只是随便填充4个字节,用于ret的地址。
PBYTE pfun=(PBYTE)fun;
while (*pfun!=0xc3)*p++=*pfun++; //写入编译后的函数
*p++=0x58;
*p++=0x58;
*p++=0x58;
*p++=0x58;
*p++=0x58; //pop eax,弹出4个参数加一个ret的地址。
*p++=0x61; //popad
AddCodeAtEntry(Code,p-Code); //代码加入入口处。
return 0;
}
|
-
免费评分
-
查看全部评分
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|