解密shell
# include <windows.h>
# include <stdio.h>
int main() {
// 1.读取当前执行程序,然后取出最后一个节的模块数据进行解密
char shellpath[256];
GetModuleFileName(NULL, shellpath, 256);//得到当前模块路径,也就是exe的路径
FILE* p = fopen(shellpath, "rb");
//判断打开情况
if (!p) {
printf("文件打开失败\n");
}
//判断文件大小
fseek(p, 0, SEEK_END);
int d = ftell(p);
fseek(p, 0, SEEK_SET);
//开始读取文件
PDWORD ShellBuf = malloc(d);
memset(ShellBuf, 0, d);
fread(ShellBuf, 1, d, p);
if (!fread) {
printf("读取失败\n");
free(ShellBuf);
}
//壳子的PE
PIMAGE_DOS_HEADER dos = NULL;
PIMAGE_NT_HEADERS nt = NULL;
PIMAGE_FILE_HEADER file = NULL;
PIMAGE_OPTIONAL_HEADER opt = NULL;
PIMAGE_SECTION_HEADER jb0 = NULL;
dos = (PIMAGE_DOS_HEADER)ShellBuf;
nt = (PIMAGE_NT_HEADERS)((DWORD)ShellBuf + dos->e_lfanew);
file = (PIMAGE_FILE_HEADER)((DWORD)nt + 4);
opt = (PIMAGE_OPTIONAL_HEADER)((DWORD)file + 20);
jb0 = (PIMAGE_SECTION_HEADER)((DWORD)opt + 0xE0);
printf("%x\n", file->NumberOfSections);
//开始定位最后一个节,并且返回最后一个节的大小,这里定义一个指针进行接收节的偏移
int x = (DWORD)file->NumberOfSections - 1;//节的数量减1
PBYTE Cobin= ((PBYTE)ShellBuf + (jb0 + x)->PointerToRawData);//最后一个节文件中偏移的位置,也就是开始位置
DWORD SrcSize= (jb0 + x)->SizeOfRawData;//返回最后一个节的大小
//开始解密
for (int i = 0; i < SrcSize; i++) {
Cobin[i] ^= 8888;
}
PBYTE SrcBuf = malloc(SrcSize);
memcpy(SrcBuf, Cobin, SrcSize);
//SRC的PE
PIMAGE_DOS_HEADER Srcdos = NULL;
PIMAGE_NT_HEADERS Srcnt = NULL;
PIMAGE_FILE_HEADER Srcfile = NULL;
PIMAGE_OPTIONAL_HEADER Srcopt = NULL;
PIMAGE_SECTION_HEADER Srcjb0 = NULL;
Srcdos = (PIMAGE_DOS_HEADER)SrcBuf;
Srcnt = (PIMAGE_NT_HEADERS)((DWORD)SrcBuf + Srcdos->e_lfanew);
Srcfile = (PIMAGE_FILE_HEADER)((DWORD)Srcnt + 4);
Srcopt = (PIMAGE_OPTIONAL_HEADER)((DWORD)Srcfile + 20);
Srcjb0 = (PIMAGE_SECTION_HEADER)((DWORD)Srcopt + 0xE0);
//3、以挂起的形式创建进程:CreateProcess
STARTUPINFO si = { 0 }; //启动信息结构体
PROCESS_INFORMATION pi;//进程信息结构体
ZeroMemory(&pi, sizeof(pi));//给结构体赋初始值全部为0
si.cb = sizeof(si);//启动信息结构体结构体的大小,必须写
BOOL res = CreateProcess(
shellpath,// 应用程序名(可执行文件)
NULL, // 命令行参数
NULL, // 进程对象的安全属性
NULL, // 主线程对象的安全属性
FALSE, // 指示子进程是否继承父进程的句柄
CREATE_SUSPENDED, // 进程创建标志,控制台分开,CREATE_SUSPENDED这个参数是以挂起的形式创建一个新的进程
NULL, // 新的环境变量块指针
NULL, // 当前目录的路径
&si, // 启动信息结构体
&pi // 进程信息结构体
);
CONTEXT contest;//创建存储线程结构体
contest.ContextFlags = CONTEXT_FULL;//获取某一段寄存器的值,要哪段就写哪段
BOOL ok = GetThreadContext(pi.hThread, &contest);//获取线程上下文内容,也就是寄存器
// 加载 ntdll.dll
HMODULE hNtdll = LoadLibrary("ntdll.dll");
if (hNtdll == NULL) {
return 1;
}
typedef DWORD(WINAPI* _TZwUnmapViewOfSection)(HANDLE, PVOID);
_TZwUnmapViewOfSection pZwUnmapViewOfSection = (_TZwUnmapViewOfSection)GetProcAddress(hNtdll, "ZwUnmapViewOfSection");
NTSTATUS status = pZwUnmapViewOfSection(pi.hProcess, (PVOID)opt->ImageBase);
printf("卸载成功:%d\n", status);
//将SRC进程拉伸
PBYTE NewSrcBuf = malloc(Srcopt->SizeOfImage);
memset(NewSrcBuf, 0, Srcopt->SizeOfImage);
//移动头部
memcpy(NewSrcBuf, SrcBuf, Srcopt->SizeOfHeaders);
printf("节数:%d\n", Srcfile->NumberOfSections);
printf("大小:%d\n", Srcopt->SizeOfImage);
//接下来复制节,节得复制需要根据节表提供得信息进行复制,复制次数等于节得个数
for (int i = 0; i < Srcfile->NumberOfSections; i++) {//从文件buf 复制到imagebuf
memcpy((LPVOID)(((DWORD)NewSrcBuf) + (Srcjb0 + i)->VirtualAddress), (LPVOID)((DWORD)SrcBuf + (Srcjb0 + i)->PointerToRawData), (Srcjb0 + i)->SizeOfRawData);
}
//获取SRC的IMAGEBASE
LONGLONG SrcImageBase = Srcopt->ImageBase;
LONGLONG SrcImageBufferSize = Srcopt->SizeOfImage;
// 在傀儡进程的SRC的ImageBase处申请SizeOfImage大小的内存
LPVOID pImageBase = VirtualAllocEx(pi.hProcess, (LPVOID)SrcImageBase, SrcImageBufferSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
//将SRC内存镜像复制到傀儡进程4GB中
if (NULL == WriteProcessMemory(pi.hProcess, (LPVOID)SrcImageBase, NewSrcBuf, SrcImageBufferSize, NULL))
{
printf("写入源程序内存镜像失败\n");
TerminateThread(pi.hThread, 0);
return -1;
}
contest.Eax = Srcopt->AddressOfEntryPoint + SrcImageBase;
PDWORD ebx8 = contest.Ebx + 8;
WriteProcessMemory(pi.hProcess, &ebx8, &SrcImageBase, 4, NULL);
SetThreadContext(pi.hThread, &contest);
// 恢复线程
ResumeThread(pi.hThread);
free(SrcBuf);
free(NewSrcBuf);
system("pause");
return 0;
}
加密部分
#include<stdio.h>
#include<windows.h>
#define IMAGE_SIZEOF_SHORT_NAME
#define out "H:\\滴水工具\\IPMsg3\\加密后.exe"
PDWORD ReadFile1(IN LPSTR file, OUT PDWORD* BUF) {
//读取文件
FILE* p = fopen(file, "rb");
//判断打开情况
if (!p) {
printf("文件打开失败\n");
}
//判断文件大小
fseek(p, 0, SEEK_END);
int d = ftell(p);
fseek(p, 0, SEEK_SET);
//开始读取文件
char* buf = malloc(d);
memset(buf, 0, d);
fread(buf, 1, d, p);
if (!fread) {
printf("读取失败\n");
free(buf);
}
*BUF = buf;
buf = NULL;
fclose(p);
return d;
}
PVOID ADDjie(IN PDWORD SHELLBUF, IN DWORD filesize, IN DWORD shellsize, IN PDWORD FILEBUF) {
if (!SHELLBUF) {
printf("加载失败\n");
return 0;
}
PIMAGE_DOS_HEADER dos = NULL;
PIMAGE_NT_HEADERS nt = NULL;
PIMAGE_FILE_HEADER file = NULL;
PIMAGE_OPTIONAL_HEADER opt = NULL;
PIMAGE_SECTION_HEADER jb0 = NULL;
dos = (PIMAGE_DOS_HEADER)SHELLBUF;
nt = (PIMAGE_NT_HEADERS)((DWORD)SHELLBUF + dos->e_lfanew);
file = (PIMAGE_FILE_HEADER)((DWORD)nt + 4);
opt = (PIMAGE_OPTIONAL_HEADER)((DWORD)file + 20);
jb0 = (PIMAGE_SECTION_HEADER)((DWORD)opt + 0xE0);
//申请内存时多D
int d = filesize + shellsize;
PDWORD NEWshellbuf = malloc(d);
memset(NEWshellbuf, 0, d);
//修改新增节的数据
file->NumberOfSections = (DWORD)file->NumberOfSections + 1;
DWORD T = ((DWORD)file->NumberOfSections - 1);
opt->SizeOfImage = (DWORD)opt->SizeOfImage + filesize;
(jb0 + T)->Name[IMAGE_SIZEOF_SHORT_NAME 0] = 0x2E;
(jb0 + T)->Name[IMAGE_SIZEOF_SHORT_NAME 1] = 0x74;
(jb0 + T)->Name[IMAGE_SIZEOF_SHORT_NAME 2] = 0x74;
(jb0 + T)->Name[IMAGE_SIZEOF_SHORT_NAME 3] = 0x74;
(jb0 + T)->Name[IMAGE_SIZEOF_SHORT_NAME 4] = 0x74;
(jb0 + T)->Misc.VirtualSize = filesize;
(jb0 + T)->VirtualAddress = (DWORD)(jb0 + (T - 1))->VirtualAddress + 0x1000;
//(jb0 + T)->VirtualAddress = 0x20000;
(jb0 + T)->SizeOfRawData = filesize;
(jb0 + T)->PointerToRawData = (DWORD)(jb0 + (T - 1))->PointerToRawData + (DWORD)(jb0 + (T - 1))->SizeOfRawData;
((jb0 + T))->Characteristics = 0x60000020;
//memcpy(NEWshellbuf, SHELLBUF, shellsize);//这里是移动壳子,也就是shell
memcpy(NEWshellbuf, SHELLBUF, shellsize);
//这里原本的程序移动结束,现在开始移动加密数据,移动到最后一个节
//存储位置是最后一个节的文件 偏移开始
LPVOID cobin = ((DWORD)NEWshellbuf + shellsize);
//复制位置SHELLBUF
//复制大小D
memcpy(cobin, FILEBUF, filesize);//这里移动SRC 移动到最后一个节得开始位置 移动大小就是filesize
//存盘
MemeryTOFile(NEWshellbuf, d, out);
}
void EnterSource(IN PBYTE SIZE, OUT PBYTE fileBUF) {
//简单的异或加密,循环加密
for (int i = 0; i < SIZE; i++) {
fileBUF[i] ^= 8888;
}
printf("加密成功\n");
printf("%d\n", SIZE);
}
BOOL MemeryTOFile(IN LPVOID Buffer, IN size_t size, OUT LPSTR File) {
FILE* p1 = NULL;
p1 = fopen(File, "wb");
if (!p1) {
printf("文件打开失败\n");
}
fwrite(Buffer, size, 1, p1);
if (!fwrite) {
printf("存盘失败\n");
free(Buffer);
}
else
{
printf("存盘成功\n");
}
fclose(p1);
p1 = NULL;
return 0;
}
int main() {
char filename_src[256] = "H:\\滴水工具\\IPMsg3\\ipmsg.exe";
char filename_shell[256] = "H:\\C语言学习\\加壳项目解密部分\\Debug\\加壳项目解密部分.exe";
//char filename_shell[256] = "H:\\C语言学习\\解密1\\Debug\\解密1.exe";
//char filename_shell[256] = "H:\\C语言学习\\解密壳部分\\Debug\\解密壳部分.exe";
PDWORD filebuf = NULL;
DWORD filesize = NULL;
PDWORD shellbuf = NULL;
DWORD shellsize = NULL;
filesize = ReadFile1(filename_src, &filebuf);
shellsize=ReadFile1(filename_shell, &shellbuf);
//加密
EnterSource(filesize, filebuf);
//放到节后面
ADDjie(shellbuf, filesize, shellsize, filebuf);
return 0;
}