滴水Win32練習殼(傀儡進程)的學習與實現


前言:花了一天時間寫完之后,自己困惑了好久,因為自己不會用,一直沒有看到視頻中的演示過程,糾結許久,最后看了下前面的演示教程發現懂了。。。

學習感受:一種變相替換CreateProcess所要運行的進程的方法,這個方法被稱作為“傀儡進程”

加密具體代碼參考:https://github.com/adezz/PeDialog

解密具體代碼參考:https://github.com/adezz/Shell-Of-Water

加密實現:

void AddWaterShell(){
	//--------------------------------------加密過程--------------------------------------
	TCHAR szBufferSrc[MAX_PATH];
	TCHAR szBufferShell[MAX_PATH];
	TCHAR* szBufferNew;

	memset(szBufferSrc,0,MAX_PATH);
	memset(szBufferShell,0,MAX_PATH);

	PVOID pFileBufferSrc = NULL;
	PVOID pFileBufferShell = NULL;

	PVOID pFileNewBufferShell = NULL;

	DWORD dwBufferLengthSrc = 0;
	DWORD dwBufferLengthShell = 0;

	GetWindowText(hShellEdit1,szBufferShell,MAX_PATH); // shell file 
	GetWindowText(hShellEdit2,szBufferSrc,MAX_PATH); // shell file 

	MyReadFile(&pFileBufferSrc,&dwBufferLengthSrc,szBufferSrc); //src

	XorEncryptAAA((char*)pFileBufferSrc,dwBufferLengthSrc);

	MyReadFile(&pFileBufferShell,&dwBufferLengthShell,szBufferShell);// shell 

	ShellAddNewSectionAndData(pFileBufferShell, &dwBufferLengthShell, &pFileNewBufferShell, pFileBufferSrc, dwBufferLengthSrc); // (1) 定為到SHELL文件的最后一個節	
	
	szBufferNew = &szBufferShell[0];
	strcat(szBufferNew, ".exe");

	MyWriteFile(pFileNewBufferShell,dwBufferLengthShell, szBufferNew);
}

殼源程序(解密):

int main(int argc, char* argv[])
{
	//--------------------------------------解密過程--------------------------------------
	//獲取當前程序運行路徑
	char FilePathSelf[255] = {0};
	GetModuleFileName(NULL, FilePathSelf, 255);

	// 1、讀取當前殼子程序本身 數據
	PVOID pFileBufferShell = NULL;
	DWORD dwBufferLengthShell = 0;
	MyReadFile(&pFileBufferShell,&dwBufferLengthShell,FilePathSelf);

	
	// 2、解密源文件,獲取源文件的imagebase sizeofimage數據
	PVOID pFileBufferSrc = NULL;	
	DWORD dwBufferLengthSrc = 0;
	DWORD dwBufferImageBaseSrc = 0;
	// dwBufferLengthSrc = GetSizeOfImage(pFileBufferShell);
	GetSrcDataFromShell(pFileBufferShell, &pFileBufferSrc, &dwBufferLengthSrc,&dwBufferImageBaseSrc);
	
	// 3、拉伸PE  pImageBufferSrc
	PVOID pImageBufferSrc = NULL;
	CopyFileBufferToImageBuffer(pFileBufferSrc,&pImageBufferSrc);

	// 4、以掛起方式運行殼程序進程
	STARTUPINFO si = {0};
	PROCESS_INFORMATION pi;
	si.cb = sizeof(si);
	::CreateProcess(FilePathSelf,NULL,NULL,NULL,NULL,CREATE_SUSPENDED, NULL,NULL,&si,&pi);
	printf("error is %d\n", GetLastError());

	DWORD dwImageBaseShell = GetImageBase(pFileBufferShell); // 獲取殼子程序自身的imagebase
	
	//5、卸載外殼程序的文件鏡像
	typedef long NTSTATUS;
	typedef NTSTATUS(__stdcall *pfnZwUnmapViewOfSection)(unsigned long ProcessHandle, unsigned long BaseAddress);
	
	pfnZwUnmapViewOfSection ZwUnmapViewOfSection = NULL;
	HMODULE hModule = LoadLibrary("ntdll.dll");
	if(hModule){
		ZwUnmapViewOfSection = (pfnZwUnmapViewOfSection)GetProcAddress(hModule, "ZwUnmapViewOfSection");
		if(ZwUnmapViewOfSection){
			if(ZwUnmapViewOfSection((unsigned long)pi.hProcess, dwImageBaseShell)){ // 卸載掉 殼子程序自身的ImageBase 地址
				printf("ZwUnmapViewOfSection success\n");
			}
		}
		FreeLibrary(hModule);
	}
	
	//6、在指定的位置(src的ImageBase)申請指定大小(src的SizeOfImage)的內存(VirtualAllocEx)
	LPVOID status = NULL;
	status = VirtualAllocEx(pi.hProcess, (LPVOID)dwBufferImageBaseSrc,dwBufferLengthSrc,MEM_RESERVE | MEM_COMMIT,PAGE_EXECUTE_READWRITE);
	printf("VirtualAllocEx: %x\n",status);
	printf("error is %d\n", GetLastError());


	if(status != NULL){
		printf("7777777\n");
		//7、如果成功,將Src的PE文件拉伸 復制到該空間中
		WriteProcessMemory(pi.hProcess, (LPVOID)dwBufferImageBaseSrc, pImageBufferSrc, dwBufferLengthSrc, NULL);

	}else{
		//8、如果申請空間失敗,但有重定位表:在任意位置申請空間,然后將PE文件拉伸、復制、修復重定位表。
		printf("8888888\n");
		PIMAGE_BASE_RELOCATION pRelocationDirectory = NULL;
		DWORD pRelocationDirectoryVirtual = 0;
		
		DWORD NumberOfRelocation;
		PWORD Location;
		DWORD RVA_Data;
		WORD reloData;
		DWORD FOA;
		DWORD dwTempImageBaseSrc = dwBufferImageBaseSrc + 0x50000;
		
		pRelocationDirectoryVirtual = GetRelocationTable(pFileBufferSrc); //當前重定位表的虛擬地址
		printf("%x\n",pRelocationDirectoryVirtual);
		if(pRelocationDirectoryVirtual){
			RVA_TO_FOA(pFileBufferSrc, pRelocationDirectoryVirtual, &FOA);
			pRelocationDirectory = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBufferSrc + FOA);
			//申請空間
			status = VirtualAllocEx(pi.hProcess, (LPVOID)dwTempImageBaseSrc,dwBufferLengthSrc,MEM_RESERVE | MEM_COMMIT,PAGE_EXECUTE_READWRITE);
			ChangesImageBase(pFileBufferSrc, dwTempImageBaseSrc);
			WriteProcessMemory(pi.hProcess, (LPVOID)dwTempImageBaseSrc, pImageBufferSrc, dwBufferLengthSrc, NULL);
			while(pRelocationDirectory->SizeOfBlock && pRelocationDirectory->VirtualAddress){				
				NumberOfRelocation = (pRelocationDirectory->SizeOfBlock - 8)/2;// 每個重定位塊中的數據項的數量
				Location = (PWORD)((DWORD)pRelocationDirectory + 8); // 加上8個字節
				for(DWORD i=0;i<NumberOfRelocation;i++){
					if(Location[i] >> 12 != 0){ //判斷是否是垃圾數據
						// WORD類型的變量進行接收
						reloData = (Location[i] & 0xFFF); //這里進行與操作 只取4字節 二進制的后12位
						RVA_Data = pRelocationDirectory->VirtualAddress + reloData; //這個是RVA的地址
						RVA_TO_FOA(pFileBufferSrc,RVA_Data,&FOA);
						//這里是自增的 進行修復重定位,上面的Imagebase我們改成了TempImageBase,那么改變的值就是 TempImageBase-dwBufferImageBaseSrc
						*(PDWORD)((DWORD)pFileBufferSrc+(DWORD)FOA) = *(PDWORD)((DWORD)pFileBufferSrc+(DWORD)FOA) + dwTempImageBaseSrc - dwBufferImageBaseSrc;	 // 任意位置 - Origin ImageBase			
					}
				}
				pRelocationDirectory = (PIMAGE_BASE_RELOCATION)((DWORD)pRelocationDirectory + (DWORD)pRelocationDirectory->SizeOfBlock); //上面的for循環完成之后,跳轉到下個重定位塊 繼續如上的操作
			}
			
			dwBufferImageBaseSrc = dwTempImageBaseSrc;
		}else{
			// 9、如果第6步申請空間失敗,並且還沒有重定位表,直接返回:失敗.
			printf("999999\n");
			return -1;	
		}
	}


	printf("10000000\n");

	
	// 10、修改外殼程序的Context:
	CONTEXT cont;
	cont.ContextFlags = CONTEXT_FULL; 
	::GetThreadContext(pi.hThread, &cont);

    DWORD dwEntryPoint = GetOep(pFileBufferSrc); // get oep
	cont.Eax = dwEntryPoint + dwBufferImageBaseSrc; // set origin oep

	DWORD theOep = cont.Ebx + 8;
	DWORD dwBytes=0;
	WriteProcessMemory(pi.hProcess, &theOep, &dwBufferImageBaseSrc,4, &dwBytes);

    SetThreadContext(pi.hThread, &cont);
	//記得恢復線程
    ResumeThread(pi.hThread);
	ExitProcess(0);
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM