首页 > 系统相关 >逆向 | 双进程保护模板

逆向 | 双进程保护模板

时间:2024-10-27 22:09:10浏览次数:6  
标签:逆向 int Regs dwState 0x33 printf 进程 pi 模板

逆向 | 双进程保护模板

继续补充书中的代码:

#include <stdio.h>
#include <Windows.h>
#define _PEB void

int FatherProcessMain();
int ChildProcessMain();     // 提前声明函数
int main(){
	_PEB* pPEB = 0;
	_asm{ 
		mov eax, dword ptr fs:[0x18];
		mov eax, dword ptr [eax+0x30];
		mov pPEB, eax;
	};
	BYTE BeingDebugged = (BYTE)(*((BYTE*)pPEB + 0x02));   
	// 对这里有疑问的小伙伴可以参见7.2.1节中的内容
	if(!BeingDebugged)    // 如果没有被调试,则调用父进程函数
	{
		return FatherProcessMain(); 
	}
	return ChildProcessMain(); // 如果被调试,则调用子进程函数
}

int FatherProcessMain(){
	unsigned char shellcode[] =
	{ 0x66,0xb8,0xdf,0xb0,0xdf,0x73,0x60,0x65,0x64,0xbe,
0x4e,0xf3,0x8a,0x23,0x33,0x33,0x33,0x8b,0xff,0xff,
0xff,0xff,0xc0,0x98,0x5b,0xe7,0x53,0x71,0x33,0xdb,
0x1d,0x32,0x33,0x33,0xb0,0xf7,0x37,0x6c,0x6d,0x68,
0xb0,0xf7,0x73,0x8,0xdf,0xdb,0xed,0x33,0x33,0x33,
0xb8,0xd6,0x6e,0xf0
};
	printf("I am Father \n");
	char filename[MAX_PATH];
	GetModuleFileName(0, filename, MAX_PATH); // 获取自身文件名
	STARTUPINFO  si={0};
	GetStartupInfo(&si);
	PROCESS_INFORMATION  pi={0};
	printf("path: %s \n", filename);
	// 以调试模式创建子进程
	if(!CreateProcess(filename,NULL,NULL,NULL,FALSE,DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS,NULL,NULL,&si,&pi)) //创建被调试进程
	{
		printf("fail to create subprocess! \n");
		return 0; 
	}
	printf("[f] subprocess id: %d \n", pi.dwProcessId);
	BOOL WhileDoFlag=TRUE;
	DEBUG_EVENT DBEvent ;
	DWORD dwState;
	while (WhileDoFlag) 
	{
		WaitForDebugEvent(&DBEvent, INFINITE);  // 等待调试事件
		dwState = DBG_EXCEPTION_NOT_HANDLED;
		switch(DBEvent.dwDebugEventCode)
		{
		case CREATE_PROCESS_DEBUG_EVENT:     // 子进程创建
			dwState = DBG_CONTINUE;
			break;      
		case EXIT_PROCESS_DEBUG_EVENT:       // 子进程退出
			WhileDoFlag = FALSE;
			break;
		case EXCEPTION_DEBUG_EVENT:
			switch (DBEvent.u.Exception.ExceptionRecord.ExceptionCode)  // 获取异常编号
			{
			case EXCEPTION_BREAKPOINT:
				{
					CONTEXT Regs = {0};
					Regs.ContextFlags = CONTEXT_FULL;    // 获取全部的上下文
					DWORD ret = GetThreadContext(pi.hThread, &Regs);
					if (Regs.Eip == 0x4016b6){           // 子进程人工抛出的断点
						printf("[f]: 接收到预定中断,不处理 \n");
						dwState = DBG_CONTINUE;          // 忽略,继续运行
						// dwState = DBG_EXCEPTION_NOT_HANDLED;   // 执行except handle
					}else{
						printf("[f]: 接收到int3中断 from %x \n", Regs.Eip);
						dwState = DBG_CONTINUE;
					}
					break;
				}
			case EXCEPTION_INT_DIVIDE_BY_ZERO:
				{
					CONTEXT Regs = {0};
					Regs.ContextFlags = CONTEXT_FULL;    // 获取全部的上下文
					DWORD ret = GetThreadContext(pi.hThread, &Regs);
					printf("[f]: 接收到divided by zero from %x \n", Regs.Eip);
					// 使用smc的方式修改子进程空间内容
					for (int i = 0; i < sizeof(shellcode); i ++){
						shellcode[i] ^= 0x33;
					}
					VOID* p_smccode = (VOID*)0x00401660u;   // 这里通过调试确定位置
					DWORD flOldProtect;
					
					VirtualProtectEx(pi.hProcess, p_smccode, sizeof(shellcode), PAGE_EXECUTE_READWRITE,&flOldProtect);
					BOOL bRet = WriteProcessMemory(pi.hProcess, p_smccode, shellcode, sizeof(shellcode), NULL);
					if (!bRet){
						printf("[f] WriteProcessMemory err! \n");
					}
					// 调整下一步的eip
					Regs.Eip += 2; // 跳过2字节的除0操作
					SetThreadContext(pi.hThread, &Regs);
					dwState = DBG_CONTINUE;    // 继续运行
					break;
				}
			}
			break;
		}    
		ContinueDebugEvent(pi.dwProcessId, pi.dwThreadId, dwState);   // 继续执行子进程的线程
	}
	
	CloseHandle(pi.hProcess);   // 关闭相应的句柄
	CloseHandle(pi.hThread);
	return 0;
}


// 代码长度54字节, 编译完成后手动删除这个函数中的字节码
void smc_code(){
	printf("[win] you reach the real path of child process! \n");
}

int ChildProcessMain(){
	printf("I am Child. \n");
	int a = 1;
	__try{
		__asm{
			int 3;   // 软中断
		}  
		a = a / 0;   // 触发父进程smc
		smc_code();
	} 
	__except(1)
	{
		printf("child err. \n");
		exit(-1);    // 调试器不处理异常,说明程序没有正常运行,直接退出
	}
	printf("child over. \n");
	return 0;
}

标签:逆向,int,Regs,dwState,0x33,printf,进程,pi,模板
From: https://www.cnblogs.com/Mz1-rc/p/18509116

相关文章

  • C++ 模板编程:解锁高效编程的神秘密码
     快来参与讨论......
  • 多项式模板
    #include<bits/stdc++.h>#defineFor(i,x,y)for(inti=(x);i<=(y);i++)#definesz(v)(int)(v.size())usingnamespacestd;intksm(intx,inty,intp){intv=1;x%=p;while(y)v=1ll*v*((y&1)?x:1)%p,x=1l......
  • P3370 【模板】字符串哈希
    【模板】字符串哈希题目描述如题,给定NNN个字符串(第iii个字符......
  • js逆向,自动吐环境代码
    functionget_enviroment(proxy_array){for(vari=0;i<proxy_array.length;i++){handler='{\n'+'get:function(target,property,receiver){\n'+'console.log("方法:","get","对象:"......
  • NET8在Linux下以守护进程方式运行
    NET8在Linux下以守护进程方式运行守护进程sudoapt-getinstallsupervisor配置cd/etc/supervisor/conf.d#进入配置目录vimzhongtai.conf#创建zhongtai命名的配置文件[program:zhongtai]#程序名称command=dotnetzhongtai.dll#要执行的命令zhongtai是程序名称directory=......
  • 解析 Vue 模板的本质:从语法糖到渲染过程
    大家耳熟能详的表述如下:Vue模板的本质其实是一种声明式渲染的形式,它在开发过程中提供了将组件的结构与逻辑分离的便利。也就是说,模板template的存在只是为了让我们以更直观的方式描述界面的结构,然而在运行时,模板其实是不存在的,它在底层会被Vue编译为更高效的渲染函数......
  • js逆向实战之某网游登录参数password加密
    声明:本篇文章仅用于知识分享,不得用于其他用途网址:https://www.37.com/加密逻辑访问网址,输入用户名和密码,看触发哪些数据包。注意:这里的流量包要选择all,如果选择fetch/XHR则看不到任何数据包。明显看到password被加密了,先去搜索url中的关键字api/login.php。可以看到......
  • linux查看某个进程的内存占用
    在Linux中,查看某个进程的内存占用可以通过多种方法实现。以下是几种常用的方式:1.使用 top 命令top 命令可以实时显示系统中运行的进程,并且显示每个进程的内存使用情况。运行 top 命令:top在 top 界面中,找到你想要查看的进程:%MEM:表示进程使用的物理内存的百分......
  • PbootCMS模板当前栏目标签
    当前栏目标签适用范围:在列表页或详情页使用。标签作用:用于输出当前栏目的相关信息。示例代码:html {sort:tcode}当前栏目的顶级栏目编码{sort:topname}当前栏目的顶级栏目名称{sort:toplink}当前栏目的顶级栏目链接{sort:pcode}当前栏目的父栏目编码{sort:parentname......
  • js逆向实战之某天下登陆参数pwd加密逻辑
    声明:本篇文章仅用于知识分享,不得用于其它用途网址:https://passport.fang.com/加密逻辑随便输入用户名和密码,看触发的数据包。可以看到pwd明显被加密了,全局搜索url中的关键字loginwithpwdStrong.api。只有两处,全部打上断点,重新登录一次,看触发哪个。触发了jquery这里,并且......