忘了说前提了,这个函数在exe文件中的地址是已知的,但没有地址保存这个函数的地址

解决方案 »

  1.   

    分两种 改exe 和动态改代码, 
    先分清楚是哪种!改exe, 用IDA, hiew 手动改, 新函数超出原函数大小就比较麻烦, 需要新建段, 或者用空余动态改代码
      VirtualAllocEx 分配内存, Write代码过去
      在原函数的头改成一个Jmp 指令, jmp偏移根据当前地址 和VirtualAllocEx 得到的地址计算出来
      

  2.   

    原函数头要是能改和已经替换了有啥差别这种方法需要改动原程序的代码有没有不需要改动原程序文件的,直接在自己的程序里替换,像hook DLL里的函数一样
      

  3.   

    hook DLL里的函数 也是要要改动原程序, 只不过它把头保存在另外的地方
      

  4.   

    Hook DLL可以直接在高级语言里把入口地址替换掉
    不用改动原文件本身如果改动原文件本身,如果原文件更新了,原文件可能就废了,假设这是个网络游戏Hook DLL只要再改变地址
      

  5.   

    可能我没说清楚
    用注入DLL的方式,可以直接修改输入地址表里Thunk保存的函数地址exe文件没有地址表保存函数地址知道原函数地址的情况下,除了用汇编reject外,还有办法把这个函数替换成我自己的函数吗?就像改输入表里的函数一样
      

  6.   

    本人写过一个<完全重定位代码“卡卡跑丁车单机版”外挂>http://blog.csdn.net/lisunlin0/archive/2007/05/12/1605488.aspx,
    里面的函数处理跟你的要求很相似,你可以下载源代码看看.
      

  7.   

    好吧
    最后一个问题
    VirtualAllocEx分配了内存后,怎么才能把我的函数write进这个地址?
    在高级语言里,不是reject
      

  8.   

    WriteProcessMemory,但是不知道我的函数的大小是多少,而且我的函数是在我的进程地址空间
      

  9.   

    BOOL WriteProcessMemory(
      HANDLE hProcess,  // handle to process whose memory is written to
      LPVOID lpBaseAddress,
                        // address to start writing to  VirtualAllocEx分配了内存返回的
      LPVOID lpBuffer,  // pointer to buffer to write data to   你的函数地址
      DWORD nSize,      // number of bytes to write
      LPDWORD lpNumberOfBytesWritten 
                        // actual number of bytes written
    );有些人在函数后面加一个没用的函数用来计算大小, 这种方法必须工程全部重新编译才正确大小一般是自己估计, 大些没关系
      

  10.   

    void HookDisplay(void)
    {
    _asm
    {
    pushad
    }
    //定义参数
    _asm
    {
    //读出参数
    }
    DWORD dCallAddress = 0x5c8340;
    ::AfxMessageBox("OK");
    _asm
    {
    popad
    call dCallAddress
    }

    } pAddress = VirtualAlloc(NULL, nSize, MEM_RESERVE|MEM_TOP_DOWN|MEM_COMMIT , PAGE_READWRITE );
    if( NULL == pAddress)
    return  FALSE;
    itoa((DWORD)pAddress, szAddress, 16);
            //这里函数地址的写法有问题吗?写进去的内容不是我想要的
    if(FALSE == WriteProcessMemory(hSoul,pAddress, HookDisplay, nSize, NULL))
    return FALSE;
    ::AfxMessageBox(szAddress); return TRUE;
      

  11.   

    WriteProcessMemory(hSoul,pAddress,   HookDisplay,   nSize,   NULL)) 这里的HookDisplay 可能会有问题, 因为可能HookDisplay 可能是一个类似IAT的表要自己判断它是否是实际地址,DWORD GetFunRealAddress(VOID * pFun)
    {
    PBYTE pCode;
    DWORD dwAddress = 0;
    DWORD dwOffset;
    pCode = (PBYTE)pFun;
    if (pCode == NULL) 
    {
    return NULL;
    } dwAddress = (DWORD)pFun;
    if(pCode[0] == 0xFF && pCode[1] == 0x25) // jmp [+imm32]
    {
    dwOffset = *(DWORD *)*(DWORD *)(&pCode[1]);
    dwAddress = (DWORD)pCode + 5 + dwOffset;
    }
    else if(pCode[0] == 0xE9) // jmp +imm32
    {
    dwOffset = *(DWORD *)(&pCode[1]);
    dwAddress = (DWORD)pCode + 5 + dwOffset;
    }
    else if(pCode[0] == 0xEB) // jmps (short)
    {
    } return dwAddress;
    }
      

  12.   

    楼主的意思是一入门的本书都不用看,来CSDN提几个问题,就可以了解Windows的编程机理了?
    建议楼主还是务实点,从路边旧书摊上面随便买本关于windows编程的书瞅上几眼.
      

  13.   

    lisunlin0
    windows程序设计,windows核心编程,黑客反汇编,win32汇编,加密与解密第二版
    我看了这些
    请问还要再看什么?
    你觉得这是入门?那你给我个答案,不用汇编改原文件,给我个答案,这100分给yofoo,再送你200分
      

  14.   

    谢谢Yofoo
    可以用了
    过一会我就结贴
    能不能跟我讲讲原理?
    或者推荐我看个贴子
      

  15.   

    最最后一个问题
    为什么我把原exe文件的call
    替换成我分配后的地址然后call
    跑不到我的地址,直接跳到异常处理程序了
    是分配空间位置问题么?还是访问权限问题?还是作用域问题?还是
      

  16.   

    用Detours吧,稳定易用.如果我前面的回复有什么口吻上的冒犯,请不要记在心上.我认为在这些细枝末节上花费太多时间不值得(当然它们也很重要).贴个我以前自己写的替换方式HOOK的代码(后来发现了Detours,就再也没有更新过了)
    //-----------------------------ULHook.h-------------------------------//
    // Write by Sunline 2003.04, [email protected]#ifndef __ULHOOKM__H_
    #define __ULHOOKM__H_
    #include "windows.h"
    /*典型的代码替换法API Hook
    经典的代码替换法API Hook过程中如果要实现原来API的功能的时候要将改写的部分还原,再调用,在多线程中可能存在线程切换时的错误
    改进的办法是将原API头部的适当长度的代码保存为一个buffer,需要原API功能时,调用这个buffer,
    例:
    原来Messagebox: 修改后: Messagebox: myMsg: ProceHead:
    8BFF  mov         edi,edi E9xxxxxxxx jmp myMsg ... 8BFF  mov         edi,edi
    55    push        ebp       55    push        ebp
    8BEC  mov         ebp,esp 8BEC  mov         ebp,esp 
    (theNcode): E9xxxxxxxx jmp   theNcode
    833D1C04D77700 cmp [77D7041Ch],0 833D1C04D77700 cmp [77D7041Ch],0
    ...
    力求克服代码替换法的不足
    */
    class CULHook
    {
    public:
    CULHook(LPSTR pszModName, LPSTR pszFuncName, PROC pfnNew);
    CULHook(PROC pfnOrig, PROC pfnNew);
    virtual ~CULHook();
    public:
    bool Hook(bool bHook);
    PROC OrigFunc(void);
    PROC operator()();
    private:
    int GetOpLen(unsigned char *buffer, int buflen);
    protected:
    byte m_bProcHead[32];
    PROC m_pfnOrig; //目标API函数的地址
    PROC m_pfnNew; //替代函数地址
    BYTE m_bNewHead[5]; //新构建的5个字节
    HMODULE m_hModule;
    };#endif //__ULHOOKM__H_
      

  17.   

    用Detours吧,稳定易用.如果我前面的回复有什么口吻上的冒犯,请不要记在心上.我认为在这些细枝末节上花费太多时间不值得(当然它们也很重要).贴个我以前自己写的替换方式HOOK的代码(后来发现了Detours,就再也没有更新过了)
    //-----------------------------ULHook.h-------------------------------//
    // Write by Sunline 2003.04, [email protected]#ifndef __ULHOOKM__H_
    #define __ULHOOKM__H_
    #include "windows.h"
    /*典型的代码替换法API Hook
    经典的代码替换法API Hook过程中如果要实现原来API的功能的时候要将改写的部分还原,再调用,在多线程中可能存在线程切换时的错误
    改进的办法是将原API头部的适当长度的代码保存为一个buffer,需要原API功能时,调用这个buffer,
    例:
    原来Messagebox: 修改后: Messagebox: myMsg: ProceHead:
    8BFF  mov         edi,edi E9xxxxxxxx jmp myMsg ... 8BFF  mov         edi,edi
    55    push        ebp       55    push        ebp
    8BEC  mov         ebp,esp 8BEC  mov         ebp,esp 
    (theNcode): E9xxxxxxxx jmp   theNcode
    833D1C04D77700 cmp [77D7041Ch],0 833D1C04D77700 cmp [77D7041Ch],0
    ...
    力求克服代码替换法的不足
    */
    class CULHook
    {
    public:
    CULHook(LPSTR pszModName, LPSTR pszFuncName, PROC pfnNew);
    CULHook(PROC pfnOrig, PROC pfnNew);
    virtual ~CULHook();
    public:
    bool Hook(bool bHook);
    PROC OrigFunc(void);
    PROC operator()();
    private:
    int GetOpLen(unsigned char *buffer, int buflen);
    protected:
    byte m_bProcHead[32];
    PROC m_pfnOrig; //目标API函数的地址
    PROC m_pfnNew; //替代函数地址
    BYTE m_bNewHead[5]; //新构建的5个字节
    HMODULE m_hModule;
    };#endif //__ULHOOKM__H_
      

  18.   

    //----------------------------ULHook.cpp------------------------------//
    // 改进的代码替换法Hook。
    #include "ULHook.h"CULHook::CULHook(LPSTR pszModName, LPSTR pszFuncName, PROC pfnNew)
    {
    m_hModule = ::LoadLibrary(pszModName);
    m_pfnOrig = ::GetProcAddress(m_hModule, pszFuncName);
    m_pfnNew = pfnNew;
    //构建jmp xxxxxxxx 
    m_bNewHead[0] = 0xE9;
    *(DWORD *)(m_bNewHead + 1) = (DWORD)( 0 - sizeof(m_bNewHead) + (unsigned int )m_pfnNew - (unsigned int )m_pfnOrig);//offset = desAddr - nextOPAddr
    for(int i = sizeof(m_bProcHead)-1; i>=0; i--) m_bProcHead[i] = 0x90;
    }CULHook::CULHook(PROC pfnOrig, PROC pfnNew)
    {
    m_hModule = NULL;
    m_pfnOrig = pfnOrig;
    m_pfnNew = pfnNew;
    m_bNewHead[0] = 0xE9;
    *(PDWORD)(m_bNewHead + 1) = (DWORD)( 0 - sizeof(m_bNewHead) + (unsigned int )m_pfnNew - (unsigned int )m_pfnOrig);
    for(int i = sizeof(m_bProcHead)-1; i >= 0; i--) m_bProcHead[i] = 0x90;
    }CULHook::~CULHook()
    {
    Hook(FALSE);
    if(m_hModule != NULL) ::FreeLibrary(m_hModule);
    }bool CULHook::Hook(bool bHook)
    {
    if(m_pfnOrig != NULL && m_pfnNew != NULL) //原函数和新的函数地址均有效
    {
    DWORD dwOldProtect;
    MEMORY_BASIC_INFORMATION memInfo;
    ::VirtualQuery(m_pfnOrig,&memInfo,sizeof(memInfo));
    if((memInfo.State == MEM_COMMIT) && (memInfo.Protect != PAGE_NOACCESS)) //目标函数在内存中
    {
    if(bHook) //hook the Api
    {
    unsigned char* p = (unsigned char *)m_pfnOrig;
    int length = 0;
    int offset = 0;
    do
    {
    offset = GetOpLen(p, 20);
    length += offset;
    p += offset;
    }while((length < sizeof(m_bNewHead)) && (offset != 0) );
    if(length < sizeof(m_bNewHead))
    {
    return false; //原函数的头部不适合用jmp dword ptr[xxxxxxx]代换
    }
    ::VirtualProtect(m_pfnOrig, length, PAGE_READWRITE, &dwOldProtect);
    //保存原来的执行代码,并构建供OrigFunc使用的执行代码头
    memcpy(m_bProcHead, m_pfnOrig, length);
    m_bProcHead[length] = 0xE9; //在尾部跳到原代码的执行部份
    *(DWORD *)(1 + length + m_bProcHead)= (DWORD)((unsigned int)m_pfnOrig + length -((unsigned int)&m_bProcHead + length + sizeof(m_bNewHead))); 
    //改写成新的执行代码
    ::WriteProcessMemory(::GetCurrentProcess(), (void *)m_pfnOrig, m_bNewHead, sizeof(m_bNewHead), NULL);
    ::VirtualProtect(m_pfnOrig, length, memInfo.Protect, 0);
    return true;
    }
    else //unHook the Api
    {
    ::VirtualProtect(m_pfnOrig, sizeof(m_bNewHead), PAGE_READWRITE, &dwOldProtect);
    if(memcmp(m_pfnOrig, m_bNewHead, sizeof(m_bNewHead)) == 0)
    { //写入原来的函数头
    ::WriteProcessMemory(::GetCurrentProcess(),(void *)m_pfnOrig,m_bProcHead, sizeof(m_bNewHead), NULL);
    ::VirtualProtect(m_pfnOrig, sizeof(m_bNewHead), memInfo.Protect, 0);
    return true;
    }
    ::VirtualProtect(m_pfnOrig, sizeof(m_bNewHead), memInfo.Protect, 0);
    return false;
    }
    }
    }
    return false;
    }PROC CULHook::OrigFunc()
    {
    return (PROC)&m_bProcHead[0];
    }PROC CULHook::operator()()
    {
    return (PROC)&m_bProcHead[0];
    }
    extern byte LenTab[];
    extern byte _FFTab[];
    extern byte _0FTab[];
    /*
    这个函数仅用于反汇编一个机器代码的长度
    比如"\x6A\x00\x68\x00\x30\x40\x00\xC3\xFF\x25\x00\x20\x40\x00";
    6A00 push 0 //返回 2
    6800304000 push 00403000 //返回 5
    C3 ret //返回 1
    FF2500204000 jmp DWORD ptr 00402000 //返回 6
    */int CULHook::GetOpLen(unsigned char *data, int buflen)
    {
    int length = 0;
    int asize = 0;
    int wsize = 0;
    //Scan for prefixes.
    for (;;) {
    if (*data == 0xF3 || *data == 0xF2 || *data == 0xF0 ||
    *data == 0x2E || *data == 0x36 || *data == 0x3E ||
    *data == 0x26 || *data == 0x64 || *data == 0x65) 
    {
    length++;
    data++;
    }
    else if (*data == 0x66 || *data == 0x67)
    {
    asize = 2;
    data++;
    length++;
    }
    else
    break;
    }
    //Scan for opration code
    switch(*data)
    {
    case 0x0F:
    data++;
    length += _FFTab[*data];
    break;
    case 0xFF:
    data++;
    length += _0FTab[*data];
    break;
    default:
    length += LenTab[*data];
    }
    length++;
    if(LenTab[*data] == (byte)-1)
    {
    return 0;
    }
    return length - wsize * asize;
    }
    byte _0FTab[] = 
    {// MOV 0F20 0F21 0F22 0F23
    // 
    /*
    0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F */ 
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//0
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//1
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//2
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//3
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//4
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//5
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//6
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//7
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//8
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//9
     0, -1, -1, -1, -1, -1, -1, -1,  0, -1, -1, -1, -1, -1, -1, -1,//A
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//B
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//C
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//D
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//E
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//F
    };
    byte _FFTab[] = 
    {/*
     0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F */ 
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//0
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//1
    -1, -1, -1, -1, -1,  4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//2
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//3
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//4
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//5
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//6
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//7
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//8
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//9
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//A
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//B
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//C
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//D
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//E
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//F
    };byte LenTab[] =
    {//the table will list the instruct:
    // mov: C6, C7, 88, 89, 8A, 8B, 8C, 8D, 8E,
    // A0, A1, A2, A3,
    //NOT RID 0F20, 0F21, 0F22, 0F23, it's operate on CR0-CR7
    // push: 06, 16, 1E, 50, 6A, 68, 0FA0, 0FA8
    // pushad: 60
    // popad: 61
    // cmp: 38, 39, 3A, 3B, 3C, 3D, 80, 81, 83 
    // Jump DWORD ptr [absolute]:
    // call DWORD ptr [absolute]:
    /*
    0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F */ 
    -1, -1, -1, -1, -1, -1,  0, -1, -1, -1, -1, -1, -1, -1,  0, -1,//0
    -1, -1, -1, -1, -1, -1,  0, -1, -1, -1, -1, -1, -1, -1,  0, -1,//1
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//2
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  1,  1,  1,  4, -1, -1,//3
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//4
     0, -1, -1, -1, -1,  0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//5
     0,  0, -1, -1, -1, -1, -1, -1,  4, -1,  1, -1, -1, -1, -1, -1,//6
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//7
     2,  5,  2,  2, -1, -1, -1, -1,  1,  1,  1,  1,  5,  5,  5, -1,//8
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//9
     4,  4,  4,  4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//A
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//B
    -1, -1, -1, -1, -1, -1,  2,  5, -1, -1, -1, -1, -1, -1, -1, -1,//C
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//D
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//E
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//F
    };