ps:首先谢谢滴水,谢谢他们贡献出免费的教程(质量真的还不错),也希望滴水能够出更多的有质量的进阶教程(因为要工作没法实地,只能自学),我也会购买的。
我建立一个群“滴水视频交流”,自学的朋友可以加,一起探讨,群号:495134543,请备注:看雪
正题和问题:
1. 我看滴水的视频然后写了一个壳,程序加壳后会报错
2. 加壳过程(kiwifruitshell.exe,中可以选择壳源和被加壳程序)
a. 在壳源加一个区段
b. 把被加壳的程序作为数据塞入这个区段
3. 解壳过程
a. 执行加壳后的程序,KiwifruitShell.exe_shell.exe
b. 判断是否有.kiwi区段,没有直接退出
c. 取出这个区段内容,然后new一个buff,然后把区段中的内容(其实是整个PE文件)按照内存中的样子拉伸,然后拷贝new出来的buff中
d. 阻塞创建一个进程,并且获取这个进程和主线程句柄
e. 根据获得的进程句柄,把c步骤拉中new出来的buff,拷贝到刚刚创建的进程空间中,从imagebase开始拷贝
f. 根据获得的线程句柄,把线程contex结构中的eip,设置为 ImageBase + OEP
g.让刚刚创建出来的进程中的主线程解除阻塞继续执行,然后就有上图中的报错
2. 环境是,win764 vs2010
3. 原因在什么地方了?
壳源代码,整个工程最后面会附加上:
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include "string.h"
#include "MyShell.h"
#define MAX_HEADER_SIZE 8192 //最大的pe头,是个估算值
#define OUT_PUT_BUFF_SIZE 4097 //调试信息最大的输出缓冲区
//
#define STATUS_SUCCESS 0x00000000
typedef LONG NTSTATUS;
typedef NTSTATUS (WINAPI *lfpZwUnmapViewOfSection)(IN HANDLE ProcessHandle,IN PVOID BaseAddress);
//
BOOL FileBuff2ImageBuff(BYTE *pbyFileBuff, DWORD dwFilebuffSize, BYTE *pbyImageBuff, DWORD dwImageSize);
//
void OutputDebugStringF(const char *fmt, ...);
#ifdef _DEBUG
#define DbgPrintf OutputDebugStringF
#else
#define DbgPrintf
#endif
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
HANDLE hSelfProcess = NULL;
HANDLE hTargetProcess = NULL;
BYTE *pbyFileBuff = NULL;
BYTE *pbyImageBuff = NULL;
HMODULE hNTModule = NULL;
//
BYTE byArryReadBuff[MAX_HEADER_SIZE] = {0};
DWORD dwNumRead;
hSelfProcess=OpenProcess(
//PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,
PROCESS_ALL_ACCESS,
FALSE,
GetCurrentProcessId());
ReadProcessMemory(hSelfProcess, hInstance, byArryReadBuff, 8192, &dwNumRead);
PIMAGE_DOS_HEADER pDosHeader= (PIMAGE_DOS_HEADER)byArryReadBuff;
if( IMAGE_DOS_SIGNATURE != pDosHeader->e_magic) goto CLEAN;
PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)(byArryReadBuff + pDosHeader -> e_lfanew);
if( IMAGE_NT_SIGNATURE != pNTHeader->Signature ) goto CLEAN;
PIMAGE_FILE_HEADER pFileHeader = &pNTHeader->FileHeader;
PIMAGE_OPTIONAL_HEADER pOptHeader = &pNTHeader->OptionalHeader;
PIMAGE_SECTION_HEADER pFirstSection = IMAGE_FIRST_SECTION(pNTHeader);
PIMAGE_SECTION_HEADER pLastSection = &pFirstSection[pFileHeader->NumberOfSections - 1];
char szSectionName[MAX_PATH] = {0};
memcpy(szSectionName, pLastSection->Name, IMAGE_SIZEOF_SHORT_NAME);
//
if(0 !=strcmp(szSectionName, ".kiwi")) goto CLEAN;
MessageBox(NULL, _T("被加壳了,点击继续执行"), _T("提示"), MB_OK);
//
char szFilePath[MAX_PATH] = {0};
GetModuleFileName(NULL, szFilePath, MAX_PATH - 1 );
//
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInfo;
ZeroMemory(&startupInfo, sizeof(startupInfo) );
startupInfo.cb = sizeof(startupInfo);
ZeroMemory(&processInfo, sizeof(processInfo));
//
BOOL bCreateProcessFlag =
CreateProcess(
NULL,
szFilePath,
NULL,
NULL,
FALSE,
CREATE_SUSPENDED,
NULL,
NULL,
&startupInfo,
&processInfo);
if(!bCreateProcessFlag) goto CLEAN;
DWORD dwCodeAddress= pLastSection->VirtualAddress;
DWORD dwCodeSize = pLastSection->SizeOfRawData;
pbyFileBuff = new BYTE[dwCodeSize];
if(NULL == pbyFileBuff) goto CLEAN;
ZeroMemory(pbyFileBuff, dwCodeSize);
ReadProcessMemory(
hSelfProcess,
(LPVOID)(pOptHeader->ImageBase + dwCodeAddress),
pbyFileBuff,
dwCodeSize,
&dwNumRead
);
if(0 == dwNumRead || dwNumRead <dwCodeSize) goto CLEAN;
for(DWORD i = 0; i < dwCodeSize; i++)
{
pbyFileBuff[i] ^= 0xCE;
}
//
hTargetProcess=OpenProcess(
PROCESS_ALL_ACCESS,
FALSE,
processInfo.dwProcessId);
if(NULL == hTargetProcess) goto CLEAN;
//
PIMAGE_DOS_HEADER pTargetDosHeader= (PIMAGE_DOS_HEADER)pbyFileBuff;
if( IMAGE_DOS_SIGNATURE != pTargetDosHeader->e_magic) goto CLEAN;
PIMAGE_NT_HEADERS pTargetNTHeader = (PIMAGE_NT_HEADERS)(pbyFileBuff + pTargetDosHeader -> e_lfanew);
if( IMAGE_NT_SIGNATURE != pTargetNTHeader->Signature ) goto CLEAN;
PIMAGE_FILE_HEADER pTargetFileHeader = &pTargetNTHeader->FileHeader;
PIMAGE_OPTIONAL_HEADER pTargetOptHeader = &pTargetNTHeader->OptionalHeader;
DWORD dwImageBuffSize = pTargetOptHeader->SizeOfImage;
//
pbyImageBuff = new BYTE[dwImageBuffSize];
if(NULL == pbyImageBuff) goto CLEAN;
BOOL bF2I = FileBuff2ImageBuff(pbyFileBuff, dwCodeSize, pbyImageBuff, dwImageBuffSize);
if(! bF2I) goto CLEAN;
//卸载程序
hNTModule = LoadLibrary("ntdll.dll");
if(NULL == hNTModule) goto CLEAN;
lfpZwUnmapViewOfSection ZwUnmapViewOfSection = NULL;
ZwUnmapViewOfSection = (lfpZwUnmapViewOfSection)GetProcAddress(
hNTModule,
"ZwUnmapViewOfSection");
NTSTATUS lStatus = ZwUnmapViewOfSection(hTargetProcess, (LPVOID)pOptHeader->ImageBase);
DbgPrintf("lstatus:%d", lStatus);
if(STATUS_SUCCESS != lStatus) goto CLEAN;
//
DWORD dwOldProtect, dwTmp;
VirtualProtectEx(
hTargetProcess,
(LPVOID)pTargetOptHeader->ImageBase,
pTargetOptHeader->SizeOfImage,
PAGE_EXECUTE_READWRITE,
&dwOldProtect
);
VirtualFreeEx(
hTargetProcess,
(LPVOID)pTargetOptHeader->ImageBase,
pTargetOptHeader->SizeOfImage,
MEM_DECOMMIT
);
LPVOID lpAlloc = VirtualAllocEx(
hTargetProcess,
(LPVOID)pTargetOptHeader->ImageBase,
pTargetOptHeader->SizeOfImage,
MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
if(NULL == lpAlloc) goto CLEAN;
DWORD dwNumWrite;
BOOL bWrite = WriteProcessMemory(
hTargetProcess,
(LPVOID)pTargetOptHeader->ImageBase,
pbyImageBuff,
dwImageBuffSize,
&dwNumWrite);
VirtualProtectEx(
hTargetProcess,
(LPVOID)pTargetOptHeader->ImageBase,
pTargetOptHeader->SizeOfImage,
dwOldProtect,
&dwTmp
);
if(!bWrite) goto CLEAN;
//
CONTEXT threadContext;
ZeroMemory(&threadContext, sizeof(threadContext));
threadContext.ContextFlags = CONTEXT_CONTROL;
if(! GetThreadContext(processInfo.hThread, &threadContext)) goto CLEAN;
threadContext.Eip = pTargetOptHeader->ImageBase + pTargetOptHeader->AddressOfEntryPoint;
threadContext.ContextFlags = CONTEXT_CONTROL; // 重新设置ContextFlags
SetThreadContext(processInfo.hThread, &threadContext);
//
ResumeThread(processInfo.hThread);
CLEAN:
if(NULL != hSelfProcess) CloseHandle(hSelfProcess);
if(NULL != hTargetProcess) CloseHandle(hTargetProcess);
if(NULL != pbyFileBuff) delete [] pbyFileBuff;
if(NULL != pbyImageBuff) delete [] pbyImageBuff;
if(NULL != hNTModule) FreeLibrary(hNTModule);
return 0;
}
// @doc 把文件在内存中拉伸
BOOL FileBuff2ImageBuff(BYTE *pbyFileBuff, DWORD dwFilebuffSize, BYTE *pbyImageBuff, DWORD dwImageSize)
{
ZeroMemory(pbyImageBuff, dwImageSize);
PIMAGE_DOS_HEADER pDosHeader= (PIMAGE_DOS_HEADER)pbyFileBuff;
if( IMAGE_DOS_SIGNATURE != pDosHeader->e_magic) goto FINSH_ERROR;
PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)(pbyFileBuff + pDosHeader -> e_lfanew);
if( IMAGE_NT_SIGNATURE != pNTHeader->Signature ) goto FINSH_ERROR;
PIMAGE_FILE_HEADER pFileHeader = &pNTHeader->FileHeader;
PIMAGE_OPTIONAL_HEADER pOptHeader = &pNTHeader->OptionalHeader;
//拷贝pe所有的头信息
memcpy(pbyImageBuff, pbyFileBuff, pOptHeader->SizeOfHeaders);
//拷贝各个节区
PIMAGE_SECTION_HEADER pFirstSection = IMAGE_FIRST_SECTION(pNTHeader);
for(DWORD i = 0; i < pFileHeader->NumberOfSections; i++)
{
DWORD dwCpySize= pFirstSection[i].SizeOfRawData >= pFirstSection[i].Misc.VirtualSize? pFirstSection[i].SizeOfRawData:pFirstSection[i].Misc.VirtualSize;
memcpy(
pbyImageBuff + pFirstSection[i].VirtualAddress,
pbyFileBuff + pFirstSection[i].PointerToRawData,
dwCpySize);
}
goto FINSH_OK;
FINSH_OK:
return TRUE;
FINSH_ERROR:
return FALSE;
}
//调试打印
void OutputDebugStringF(const char *fmt, ...)
{
va_list vlArgs;
char *strBuf = (char*)GlobalAlloc(GPTR, OUT_PUT_BUFF_SIZE);
ZeroMemory(strBuf, OUT_PUT_BUFF_SIZE);
va_start(vlArgs, fmt);
_vsnprintf_s(strBuf, OUT_PUT_BUFF_SIZE - 1, OUT_PUT_BUFF_SIZE -1, fmt, vlArgs);
va_end(vlArgs);
strcat_s(strBuf, OUT_PUT_BUFF_SIZE - 1, "\n");
OutputDebugStringA(strBuf);
GlobalFree(strBuf);
}
工程代码:
KiwifruitShell.rar
其中:myshell是壳源,kiwifruit_shell,是加壳的程序
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
上传的附件: