其他
程序隐藏、加壳、内存加载运行的一种实验
本文为看雪论坛优秀文章
看雪论坛作者ID:satadrover
(一)原理
文件个数(int型),密钥(char型,16字节,用的当前时间的md5值),文件大小1(int),文件名1(char型,64字节),文件大小2(int),文件名2(char型,64字节),。。。,,文件大小n(int),文件名n(char型,64字节)。
int ret = 0;
int filesize = 0;
for (int i = 0; i < cnt; i++)
{
int fz = FileHelper::getfilesize(filename[i]);
filesize += fz;
printf("file name:%s size:%d\r\n", filename[i], fz);
}
int dstbufsize = filesize + 0x1000;
unsigned char* dstblock = new unsigned char[dstbufsize];
*(int*)dstblock = flag;
// if (cnt == 1 && strstr((char*)filename[0],".exe") )
// {
// *(int*)dstblock = ONLY_ONE_EXE;
// }
// else if (cnt == 1 && strstr((char*)filename[0], ".dll"))
// {
// *(int*)dstblock = ONLY_ONE_DLL;
// }
// else if (cnt > 1 )
// {
// int flagexe = 0;
// int flagdll = 0;
// for (int i = 0;i < cnt; i ++)
// {
// if (strstr((char*)filename[i], ".dll")) {
// flagdll = 1;
// }else if (strstr(filename[i],".exe"))
// {
// flagexe = 1;
// }
// }
//
// if (flagexe && flagdll)
// {
// *(int*)dstblock = ONE_EXE_AND_ONE_DLL;
// }
// else {
// *(int*)dstblock = SOME_OTHER_FILES;
// }
// }
// else {
// return 0;
// }
unsigned char* key = dstblock + 4;
getkey(key);
*(int*)(dstblock + 4 + CRYPT_KEY_SIZE) = cnt;
unsigned char* dstbuf = dstblock + 4 + CRYPT_KEY_SIZE + 4;
int dstbuflimit = dstbufsize - 4 - CRYPT_KEY_SIZE - 4;
for (int i = 0; i < cnt; i++)
{
lstrcpyA((char*)dstbuf, filename[i]);
PathStripPathA((char*)dstbuf);
dstbuf += FILENAME_LEN;
dstbuflimit -= FILENAME_LEN;
char* lpdata = 0;
ret = FileHelper::fileReader(filename[i], &lpdata, &filesize);
if (ret > 0)
{
unsigned long cmpresssize = dstbuflimit - 4;
ret = Compress::compressdata((unsigned char*)lpdata, filesize, dstbuf + 4, &cmpresssize);
delete[] lpdata;
if (ret != 0)
{
delete dstblock;
printf("compress file:%s error:%u\r\n", filename[i], GetLastError());
return 0;
}
*(int*)(dstbuf) = cmpresssize;
dstbuf += 4;
dstbuf += cmpresssize;
dstbuflimit -= 4;
dstbuflimit -= cmpresssize;
}
else {
delete dstblock;
printf("read file:%s error\r\n", filename[i]);
return 0;
}
}
dstdatasize = dstbuf - dstblock;
CryptData(dstblock + 4 + CRYPT_KEY_SIZE, dstdatasize - 4 - CRYPT_KEY_SIZE, key, CRYPT_KEY_SIZE);
//revertkey(key);
return dstblock;
}
PeShell -bd sogou.exe sbiedll.dll -c params.dat -o out.dll
PeShell -e sogou.exe -c params.dat -o out.exe
PeShell -d sogou.exe -c params.dat -o out.dll
-be:b代表bind,绑定的意思;e代表executable,可执行的。
-bd:b代表bind,绑定的意思;d代表dll,即动态重定位文件。
-o: 输出文件,即加壳后的程序。
-c: 参数。
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union {
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
PointerToRawData = 上一个段表的值+上一个段表扇区对齐后的大小,
SizeOfRawData是段文件对齐后大小,
VirtualSize是段实际大小,
Characteristics必须是代码或者数据段,否则不会被装入内存,
IMAGE_FILE_HEADER中NumberOfSections字段加1,
IMAGE_OPTIONAL_HEADER32中SizeOfImage字段要加上该段对齐后的大小。
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
typedef struct _IMAGE_OPTIONAL_HEADER {
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;
DWORD ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
{
int ret = 0;
char szout[1024];
DWORD dwSizeOfImage = GetSizeOfImage(pFileBuff);
DWORD imagebase = GetImageBase(pFileBuff);
if (imagebase <= 0)
{
imagebase = DEFAULT_PE_BASE_ADDRESS;
}
#ifdef _MYDEBUG
wsprintfA(szout, "image base:%x,size:%x", imagebase, dwSizeOfImage);
MessageBoxA(0, szout, szout, MB_OK);
#endif
//使用MEM_RESERVE分配类型参数 Windows会以64 KB为边界计算该区域的起始地址 跟PE文件加载边界一致
//使用MEM_COMMIT分配类型参数 区域的起始和结束地址都被计算到4KB边界
//VirtualAlloc 当程序访问这部分内存时RAM内存才会被真正分配
char* chBaseAddress = (char*)lpVirtualAlloc(imagebase, dwSizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (NULL == chBaseAddress)
{
#ifdef _MYDEBUG
wsprintfA(szout, "VirtualAlloc address:%x error", imagebase);
MessageBoxA(0, szout, szout, MB_OK);
#endif
chBaseAddress = (char*)lpVirtualAlloc(0, dwSizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (NULL == chBaseAddress)
{
#ifdef _MYDEBUG
wsprintfA(szout, "VirtualAlloc address:%x error", imagebase);
MessageBoxA(0, szout, szout, MB_OK);
#endif
return NULL;
}
}
RtlZeroMemory(chBaseAddress, dwSizeOfImage);
ret = MapFile(pFileBuff, chBaseAddress);
//Reloc::recovery((DWORD)chBaseAddress);
ret = RelocationTable(chBaseAddress);
//ImportFunTable::recover((DWORD)chBaseAddress);
ret = ImportTable(chBaseAddress);
DWORD dwOldProtect = 0;
if (FALSE == lpVirtualProtect(chBaseAddress, dwSizeOfImage, PAGE_EXECUTE_READWRITE, &dwOldProtect))
{
lpVirtualFree(chBaseAddress, dwSizeOfImage, MEM_DECOMMIT);
lpVirtualFree(chBaseAddress, 0, MEM_RELEASE);
#ifdef _MYDEBUG
wsprintfA(szout, "VirtualProtect address:%x error", imagebase);
MessageBoxA(0, szout, szout, MB_OK);
#endif
return NULL;
}
ret = SetImageBase(chBaseAddress);
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)chBaseAddress;
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)(chBaseAddress + dos->e_lfanew);
#ifdef _MYDEBUG
wsprintfA(szout, "pe type:%x", nt->FileHeader.Characteristics);
MessageBoxA(0, szout, szout, MB_OK);
#endif
if (nt->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI)
{
}
else if (nt->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)
{
gType = 3;
ghPEModule = (HMODULE)chBaseAddress;
gPEImageSize = dwSizeOfImage;
ret = CallConsoleEntry(chBaseAddress);
lpVirtualFree(chBaseAddress, dwSizeOfImage, MEM_DECOMMIT);
lpVirtualFree(chBaseAddress, 0, MEM_RELEASE);
return ret;
}
if (nt->FileHeader.Characteristics & 0x2000)
{
gType = 2;
gPEImageSize = dwSizeOfImage;
ghPEModule = (HMODULE)chBaseAddress;
ret = recoverEAT(chBaseAddress);
ret = CallDllEntry(chBaseAddress);
return ret;
}
else {
gType = 1;
ghPEModule = (HMODULE)chBaseAddress;
gPEImageSize = dwSizeOfImage;
ret = CallExeEntry(chBaseAddress);
lpVirtualFree(chBaseAddress, dwSizeOfImage, MEM_DECOMMIT);
lpVirtualFree(chBaseAddress, 0, MEM_RELEASE);
return ret;
}
return TRUE;
}
(二)测试
看雪ID:satadrover
https://bbs.kanxue.com/user-home-653410.htm
# 往期推荐
3、安卓加固脱壳分享
球分享
球点赞
球在看