在分析样本时偶尔会遇到加保护壳的 Dll 文件,脱起来比较麻烦。由于加壳 Dll 文件的壳代码都是在 DllMain() 函数中,在调用 LoadLibrary() 加载 Dll 文件时,主函数就会执行。因此可以写个程序加载 Dll 文件,然后 Dump 出来,即可完成脱壳。虽然不能确定入口点和修复导入表,但代码部分应该都是正常的。具体代码如下:
#include <windows.h>
#include <winnt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
if (argc>3 || argc<2)
{
printf("Usage: DllUnpack <filename> [dumplength]/n");
return -1;
}
int nRetVal = 0;
HMODULE hModule = NULL;
unsigned uModuleOffset, uLength, uSectionNum;
unsigned i;
char szUnpackFileName[MAX_PATH];
char *endptr = NULL;
FILE *pFileOut = NULL;
DWORD dwOldProtect;
IMAGE_DOS_HEADER *pDosHeader;
IMAGE_FILE_HEADER *pFileHeader;
IMAGE_SECTION_HEADER *pSectionHeader = NULL;
IMAGE_SECTION_HEADER *pLastSectionHeader = NULL;
hModule = LoadLibrary(argv[1]);
if (hModule == NULL)
{
printf("Error: cannot load dll %s!/n", argv[1]);
return -1;
}
strncpy(szUnpackFileName, argv[1], MAX_PATH-5);
strcat(szUnpackFileName, "_un");
uModuleOffset = (unsigned)hModule;
//Get unapcked file size
VirtualProtect((LPVOID)uModuleOffset, 0x1000, PAGE_EXECUTE_READWRITE, &dwOldProtect);
pDosHeader = (IMAGE_DOS_HEADER *)uModuleOffset;
pFileHeader = (IMAGE_FILE_HEADER *)(uModuleOffset + pDosHeader->e_lfanew + sizeof(DWORD));
uSectionNum = pFileHeader->NumberOfSections;
pSectionHeader = (IMAGE_SECTION_HEADER *)((unsigned)pFileHeader +
sizeof(IMAGE_FILE_HEADER) + pFileHeader->SizeOfOptionalHeader);
if (argc == 3)
{
uLength = (unsigned)strtol(argv[2], &endptr, 16);
}
else
{
pLastSectionHeader = (IMAGE_SECTION_HEADER *)((unsigned)pSectionHeader +
(uSectionNum-1)*sizeof(IMAGE_SECTION_HEADER));
uLength = pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize;
}
//Modify the section table
for (i=0; i<uSectionNum;i++)
{
pSectionHeader[i].PointerToRawData = pSectionHeader[i].VirtualAddress;
pSectionHeader[i].SizeOfRawData = pSectionHeader[i].Misc.VirtualSize;
}
VirtualProtect((LPVOID)uModuleOffset, 0x1000, dwOldProtect, NULL);
//Creates the unpacked file
if ((pFileOut=fopen(szUnpackFileName, "wb")) == NULL)
{
printf("Error: cannot create file %s/n", szUnpackFileName);
nRetVal = -1;
goto Exit0;
}
if (fwrite((void *)uModuleOffset, uLength, 1, pFileOut) != 1)
{
printf("Error: cannot write to file %s/n", szUnpackFileName);
nRetVal = -1;
}
Exit0:
if (pFileOut)
{
fclose(pFileOut);
pFileOut = NULL;
}
if (hModule)
{
FreeLibrary(hModule);
}
return nRetVal;
}
#include <windows.h>
#include <winnt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
if (argc>3 || argc<2)
{
printf("Usage: DllUnpack <filename> [dumplength]/n");
return -1;
}
int nRetVal = 0;
HMODULE hModule = NULL;
unsigned uModuleOffset, uLength, uSectionNum;
unsigned i;
char szUnpackFileName[MAX_PATH];
char *endptr = NULL;
FILE *pFileOut = NULL;
DWORD dwOldProtect;
IMAGE_DOS_HEADER *pDosHeader;
IMAGE_FILE_HEADER *pFileHeader;
IMAGE_SECTION_HEADER *pSectionHeader = NULL;
IMAGE_SECTION_HEADER *pLastSectionHeader = NULL;
hModule = LoadLibrary(argv[1]);
if (hModule == NULL)
{
printf("Error: cannot load dll %s!/n", argv[1]);
return -1;
}
strncpy(szUnpackFileName, argv[1], MAX_PATH-5);
strcat(szUnpackFileName, "_un");
uModuleOffset = (unsigned)hModule;
//Get unapcked file size
VirtualProtect((LPVOID)uModuleOffset, 0x1000, PAGE_EXECUTE_READWRITE, &dwOldProtect);
pDosHeader = (IMAGE_DOS_HEADER *)uModuleOffset;
pFileHeader = (IMAGE_FILE_HEADER *)(uModuleOffset + pDosHeader->e_lfanew + sizeof(DWORD));
uSectionNum = pFileHeader->NumberOfSections;
pSectionHeader = (IMAGE_SECTION_HEADER *)((unsigned)pFileHeader +
sizeof(IMAGE_FILE_HEADER) + pFileHeader->SizeOfOptionalHeader);
if (argc == 3)
{
uLength = (unsigned)strtol(argv[2], &endptr, 16);
}
else
{
pLastSectionHeader = (IMAGE_SECTION_HEADER *)((unsigned)pSectionHeader +
(uSectionNum-1)*sizeof(IMAGE_SECTION_HEADER));
uLength = pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize;
}
//Modify the section table
for (i=0; i<uSectionNum;i++)
{
pSectionHeader[i].PointerToRawData = pSectionHeader[i].VirtualAddress;
pSectionHeader[i].SizeOfRawData = pSectionHeader[i].Misc.VirtualSize;
}
VirtualProtect((LPVOID)uModuleOffset, 0x1000, dwOldProtect, NULL);
//Creates the unpacked file
if ((pFileOut=fopen(szUnpackFileName, "wb")) == NULL)
{
printf("Error: cannot create file %s/n", szUnpackFileName);
nRetVal = -1;
goto Exit0;
}
if (fwrite((void *)uModuleOffset, uLength, 1, pFileOut) != 1)
{
printf("Error: cannot write to file %s/n", szUnpackFileName);
nRetVal = -1;
}
Exit0:
if (pFileOut)
{
fclose(pFileOut);
pFileOut = NULL;
}
if (hModule)
{
FreeLibrary(hModule);
}
return nRetVal;
}