• X32进程注入x64DLL到x64进程


    在x32程序中获得x64函数地址是找到这个项目,之后根据自己的理解稍微改了改代码,测试之后能够正常的注入,代码如下

    #include "stdafx.h"
    #include "x32Injectx64.h"
    #include <Windows.h>
    #include "wow64ext.h"
    
    #pragma comment(lib,"wow64ext.lib")
    
    CWinApp theApp;
    
    using namespace std;
    
    typedef struct _UNICODE_STRING {
    	USHORT    Length;    
    	USHORT	  MaximumLength; 
    	DWORD64   Buffer;     
    } UNICODE_STRING ,*PUNICODE_STRING;
    
    
    
    //这里是返回到x32模式
    char RetFar[10] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00 };
    
    UCHAR Code[] = {
    		0x48, 0x83, 0xEC, 0x28,                 // sub rsp, 0x28   ,第一个是48,这里改为cc方便调试
    		0x48, 0x31, 0xC9,                       // xor rcx, rcx
    		0x48, 0x31, 0xD2,                       // xor rdx, rdx
    		0x49, 0xB8, 0, 0, 0, 0, 0, 0, 0, 0,     // mov r8, ModuleFileName   offset +12
    		0x49, 0xB9, 0, 0, 0, 0, 0, 0, 0, 0,     // mov r9, ModuleHandle     offset +22
    		0x48, 0xB8, 0, 0, 0, 0, 0, 0, 0, 0,     // mov rax, LdrLoadDll      offset +32
    		0xFF, 0xD0,                             // call rax
    		0x48, 0x83, 0xC4, 0x28,                 // add rsp, 0x28
    
    		0xC3                                 // ret   //如果是32位需要将这里返回为32位状态,64位用它
    		
    		/*0x48, 0xB8, 0, 0, 0, 0, 0, 0, 0, 0,    // mov rax, RetFar    offset+48
    
    		0x48, 0x8B, 0x0C, 0x24,                //  mov rcx,qword ptr ss : [rsp]  
    		0x48, 0x89, 0x08,                      //  mov qword ptr ds : [rax],rcx  
    
    		0x48,0xff,0x28                         //jmp far tword ptr ds:[rax] */       
    };
    
    UCHAR code32To64[] = {
    	0xea,0x00,0x10,0x40, 0x00,0x33,0x00   //jmp 33:401000 ea
    
    };
    
    enum  InjectResult{
    	OK,
    	Error_NoSuchFile,
    	Error_OpenProcess,
    	Error_VirtualAllocEx,
    	Error_GetProcAddress,
    	Error_WriteProcessMemory,
    	Error_CreateRemoteThread
    };
    
    InjectResult Wow64Injectx64(DWORD processid, const TCHAR* file_path) {
    
    	if (!PathFileExists(file_path)) {
    		return Error_NoSuchFile;
    	}
    
    	HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processid);
    	if (INVALID_HANDLE_VALUE == handle) {
    		return Error_OpenProcess;
    	}
    
    	size_t file_path_mem_length = (size_t)::_tcslen(file_path) +1;
    	size_t paramemter_size = file_path_mem_length  * sizeof(TCHAR) + sizeof(UNICODE_STRING) + sizeof(DWORD64) ;//申请的大小
    	DWORD64 paramemter_mem_addr = (DWORD64)VirtualAllocEx64(handle, NULL, paramemter_size, MEM_COMMIT, PAGE_READWRITE);//目标地址
    	DWORD64  shell_code_addr = (DWORD64)VirtualAllocEx64(handle, NULL, sizeof(Code), MEM_COMMIT, PAGE_EXECUTE_READWRITE);//申请的shellcode的大小是多少
    	DWORD64  shell_code_32 = (DWORD64)VirtualAllocEx64(handle, NULL, sizeof(shell_code_32), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    
    	DWORD64  ret_32 = (DWORD64)VirtualAllocEx64(handle, NULL, sizeof(RetFar), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    
    	if ((!paramemter_mem_addr) || (!shell_code_addr)) {
    		return Error_VirtualAllocEx;
    	}
    
    	DWORD64 ntdll64 = GetModuleHandle64(L"ntdll.dll");
    	DWORD64 ntdll_LdrLoadDll = GetProcAddress64(ntdll64, "LdrLoadDll");
    	DWORD64 ntdll_RtlCreateUserThread = GetProcAddress64(ntdll64, "RtlCreateUserThread");
    	DWORD64 ntdll_RtlExitThread = GetProcAddress64(ntdll64, "RtlExitUserThread");
    	if (NULL == ntdll_LdrLoadDll || NULL == ntdll_RtlCreateUserThread || NULL == ntdll_RtlExitThread) {
    		return Error_GetProcAddress;
    	}
    
    
    	// Fill stubs
    	*(ULONGLONG*)((PUCHAR)Code + 12) = paramemter_mem_addr + 8;//第二个参数放到是paramemter_mem_addr+0x10
    	*(ULONGLONG*)((PUCHAR)Code + 22) = paramemter_mem_addr;//第一个参数放到是句柄
    	*(ULONGLONG*)((PUCHAR)Code + 32) = ntdll_LdrLoadDll;
    	//*(ULONGLONG*)((PUCHAR)Code + 48) = ret_32;
    
    	//*(ULONG*)((PUCHAR)code32To64+1) = shell_code_addr;
    
    
    	file_path_mem_length *= 2;//最大为多大
    	DWORD tmpSize = file_path_mem_length - 2;//当前字符串的大小
    	DWORD64 address = paramemter_mem_addr + 0x18;
    	if (!WriteProcessMemory64(handle, paramemter_mem_addr + 8, &tmpSize, 2, NULL) ||
    		!WriteProcessMemory64(handle, paramemter_mem_addr + 10, &file_path_mem_length, 2, NULL) ||
    		!WriteProcessMemory64(handle, paramemter_mem_addr + 0x10, &address, 8, NULL) ||//记录的字符串的地址,这里不是以12开始是因为8字节对齐,
    		!WriteProcessMemory64(handle, paramemter_mem_addr + 0x18, (LPVOID)file_path, (size_t)::_tcslen(file_path) * sizeof(TCHAR), NULL) ||
    		!WriteProcessMemory64(handle, shell_code_addr, Code, sizeof(Code), NULL)||
    		!WriteProcessMemory64(handle, shell_code_32, code32To64, sizeof(code32To64), NULL)||
    		!WriteProcessMemory64(handle, ret_32, RetFar, sizeof(RetFar), NULL)
    		) {
    		return Error_WriteProcessMemory;
    	}
    	DWORD64 hRemoteThread = 0;
    	struct {
    		DWORD64 UniqueProcess;
    		DWORD64 UniqueThread;
    	} client_id;
    	DWORD64 a = X64Call(ntdll_RtlCreateUserThread, 10,
    		(DWORD64)handle,					// ProcessHandle
    		(DWORD64)NULL,                      // SecurityDescriptor
    		(DWORD64)FALSE,                     // CreateSuspended
    		(DWORD64)0,                         // StackZeroBits
    		(DWORD64)NULL,                      // StackReserved
    		(DWORD64)NULL,                      // StackCommit
    		shell_code_addr,					// StartAddress,如果是注入64位进程把这里改为shell_code_addr就行
    		(DWORD64)NULL,                      // StartParameter
    		(DWORD64)&hRemoteThread,            // ThreadHandle
    		(DWORD64)&client_id);               // ClientID)//
    	if (INVALID_HANDLE_VALUE == (HANDLE)hRemoteThread) {
    		return Error_CreateRemoteThread;
    	}
    	return OK;
    }
    
    int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]){
    	cout<<"What ID You Want To Inject"<<endl;   
    	ULONG_PTR ProcessID = 0;
    	
    	printf("Input ProcessID\r\n");
    	cin>>ProcessID;
    	WCHAR file_path[] = L"C:\\64.dll";
    
    	
    	if (OK==Wow64Injectx64(ProcessID,file_path)){
    		printf("Inject Success!\n");
    	}
    	return 0;
    }
    
    
    

    这里又引发了一个问题,就是既然是通过切换cs的方式加载的dll,那么x32能不能加载x64的dll,于是把上面的代码改了改,主要是这部分的改动。

    由于启动线程之后当前的状态是x32模式下的,所以使用远跳切换cs,后面的401000不是固定,是根据后面申请的地址填的,最后当我们加载dll之后在把当前的cs给改回来(这里不改回来程序会崩掉),之后测试。最后的测试结果是不行,按照正常的理解也是不行了,如果加载导出函数,那么解析的时候是根据x32去解析x64的代码肯定是会出现问题的,有兴趣的朋友可以去试一下。改了之后的代码如下。

    
    
    //这里是返回到x32模式
    char RetFar[10] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00 };
    
    UCHAR Code[] = {
    		0x48, 0x83, 0xEC, 0x28,                 // sub rsp, 0x28   ,第一个是48,这里改为cc方便调试
    		0x48, 0x31, 0xC9,                       // xor rcx, rcx
    		0x48, 0x31, 0xD2,                       // xor rdx, rdx
    		0x49, 0xB8, 0, 0, 0, 0, 0, 0, 0, 0,     // mov r8, ModuleFileName   offset +12
    		0x49, 0xB9, 0, 0, 0, 0, 0, 0, 0, 0,     // mov r9, ModuleHandle     offset +22
    		0x48, 0xB8, 0, 0, 0, 0, 0, 0, 0, 0,     // mov rax, LdrLoadDll      offset +32
    		0xFF, 0xD0,                             // call rax
    		0x48, 0x83, 0xC4, 0x28,                 // add rsp, 0x28
    
    		//0xC3                                 // ret   //如果是32位需要将这里返回为32位状态,64位用它
    		
    		0x48, 0xB8, 0, 0, 0, 0, 0, 0, 0, 0,    // mov rax, RetFar    offset+48
    
    		0x48, 0x8B, 0x0C, 0x24,                //  mov rcx,qword ptr ss : [rsp]  
    		0x48, 0x89, 0x08,                      //  mov qword ptr ds : [rax],rcx  
    
    		0x48,0xff,0x28                         //jmp far tword ptr ds:[rax]       
    };
    
    UCHAR code32To64[] = {
    	0xea,0x00,0x10,0x40, 0x00,0x33,0x00   //jmp 33:401000 ea
    
    };
    
    enum  InjectResult{
    	OK,
    	Error_NoSuchFile,
    	Error_OpenProcess,
    	Error_VirtualAllocEx,
    	Error_GetProcAddress,
    	Error_WriteProcessMemory,
    	Error_CreateRemoteThread
    };
    
    InjectResult Wow64Injectx64(DWORD processid, const TCHAR* file_path) {
    
    	if (!PathFileExists(file_path)) {
    		return Error_NoSuchFile;
    	}
    
    	HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processid);
    	if (INVALID_HANDLE_VALUE == handle) {
    		return Error_OpenProcess;
    	}
    
    	size_t file_path_mem_length = (size_t)::_tcslen(file_path) +1;
    	size_t paramemter_size = file_path_mem_length  * sizeof(TCHAR) + sizeof(UNICODE_STRING) + sizeof(DWORD64) ;//申请的大小
    	DWORD64 paramemter_mem_addr = (DWORD64)VirtualAllocEx64(handle, NULL, paramemter_size, MEM_COMMIT, PAGE_READWRITE);//目标地址
    	DWORD64  shell_code_addr = (DWORD64)VirtualAllocEx64(handle, NULL, sizeof(Code), MEM_COMMIT, PAGE_EXECUTE_READWRITE);//申请的shellcode的大小是多少
    	DWORD64  shell_code_32 = (DWORD64)VirtualAllocEx64(handle, NULL, sizeof(shell_code_32), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    
    	DWORD64  ret_32 = (DWORD64)VirtualAllocEx64(handle, NULL, sizeof(RetFar), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    
    	if ((!paramemter_mem_addr) || (!shell_code_addr)) {
    		return Error_VirtualAllocEx;
    	}
    
    	DWORD64 ntdll64 = GetModuleHandle64(L"ntdll.dll");
    	DWORD64 ntdll_LdrLoadDll = GetProcAddress64(ntdll64, "LdrLoadDll");
    	DWORD64 ntdll_RtlCreateUserThread = GetProcAddress64(ntdll64, "RtlCreateUserThread");
    	DWORD64 ntdll_RtlExitThread = GetProcAddress64(ntdll64, "RtlExitUserThread");
    	if (NULL == ntdll_LdrLoadDll || NULL == ntdll_RtlCreateUserThread || NULL == ntdll_RtlExitThread) {
    		return Error_GetProcAddress;
    	}
    
    
    	// Fill stubs
    	*(ULONGLONG*)((PUCHAR)Code + 12) = paramemter_mem_addr + 8;//第二个参数放到是paramemter_mem_addr+0x10
    	*(ULONGLONG*)((PUCHAR)Code + 22) = paramemter_mem_addr;//第一个参数放到是句柄
    	*(ULONGLONG*)((PUCHAR)Code + 32) = ntdll_LdrLoadDll;
    	*(ULONGLONG*)((PUCHAR)Code + 48) = ret_32;
    
    	*(ULONG*)((PUCHAR)code32To64+1) = shell_code_addr;
    
    
    	file_path_mem_length *= 2;//最大为多大
    	DWORD tmpSize = file_path_mem_length - 2;//当前字符串的大小
    	DWORD64 address = paramemter_mem_addr + 0x18;
    	if (!WriteProcessMemory64(handle, paramemter_mem_addr + 8, &tmpSize, 2, NULL) ||
    		!WriteProcessMemory64(handle, paramemter_mem_addr + 10, &file_path_mem_length, 2, NULL) ||
    		!WriteProcessMemory64(handle, paramemter_mem_addr + 0x10, &address, 8, NULL) ||//记录的字符串的地址,这里不是以12开始是因为8字节对齐,
    		!WriteProcessMemory64(handle, paramemter_mem_addr + 0x18, (LPVOID)file_path, (size_t)::_tcslen(file_path) * sizeof(TCHAR), NULL) ||
    		!WriteProcessMemory64(handle, shell_code_addr, Code, sizeof(Code), NULL)||
    		!WriteProcessMemory64(handle, shell_code_32, code32To64, sizeof(code32To64), NULL)||
    		!WriteProcessMemory64(handle, ret_32, RetFar, sizeof(RetFar), NULL)
    		) {
    		return Error_WriteProcessMemory;
    	}
    	DWORD64 hRemoteThread = 0;
    	struct {
    		DWORD64 UniqueProcess;
    		DWORD64 UniqueThread;
    	} client_id;
    	DWORD64 a = X64Call(ntdll_RtlCreateUserThread, 10,
    		(DWORD64)handle,					// ProcessHandle
    		(DWORD64)NULL,                      // SecurityDescriptor
    		(DWORD64)FALSE,                     // CreateSuspended
    		(DWORD64)0,                         // StackZeroBits
    		(DWORD64)NULL,                      // StackReserved
    		(DWORD64)NULL,                      // StackCommit
    		shell_code_32,					// StartAddress,如果是注入64位进程把这里改为shell_code_addr就行
    		(DWORD64)NULL,                      // StartParameter
    		(DWORD64)&hRemoteThread,            // ThreadHandle
    		(DWORD64)&client_id);               // ClientID)//
    	if (INVALID_HANDLE_VALUE == (HANDLE)hRemoteThread) {
    		return Error_CreateRemoteThread;
    	}
    	return OK;
    }
    
    
    
     
  • 相关阅读:
    广播系统android安全:flag FLAG_RECEIVER_REGISTERED_ONLY的意义
    产品类大话设计模式——简单工厂模式
    打印数组算法:堆栈与深度优先搜索(迷宫问题)
    函数声明第四章利用函数实现指定的功能
    构造函数调用C++ 类和动态内存分配
    命令密码MySQL忘记密码恢复密码的实现方法
    线程资源PHP源码分析之线程安全模型
    编译类【COCOS2DXLUA 脚本开发之十四】解决自定义CPP类通过TOLUA++ BINDING LUACOCOS2D后编译到ANDROID运行黑屏(没有调用自定义CPP类)的问题!
    语句数据库ubuntu下mysql的常用命令
    eclipse中配置tomcat
  • 原文地址:https://www.cnblogs.com/csnd/p/16675609.html
Copyright © 2020-2023  润新知