zoukankan      html  css  js  c++  java
  • 获取其它进程内EDIT BOX内容的一种方法

    获取其它进程内EDIT BOX内容的一种方法

    呕心沥血写就(试验代码写了一大坨),修改及转载请标明出处,谢谢!

    感谢[jozu][ahakin][辟邪马甲]等高手指点。

    GetWindowText等函数在win2k及以后系统上不能获得其它进程内的EDIT BOX内容,本文使用CreateRemoteThread来解决这个问题。
    * 这不是唯一的解决方法,使用钩子等方法也可以解决这个问题。
    * 即使使用CreateRemoteThread,那么注入自己的DLL会简单一箩筐,但我这里没有使用自己的DLL,所以这是一种很差的方法,代码移植性差、代码编写复杂、代码不容易看懂,等等,但它也有一个优点:不需要制作自己的DLL ^_^。
    (不需要制作自己的DLL有另外一个大优点,不说)

    平台:IBM兼容PC指令, Windows 2K pro
    编译器:VC++6.0
    说明:
    1. 欲在目标进程内使用GetWindowText等函数,必先加载User32.dll。
    * 如果目标进程早已自己加载了User32的话,再加载一次也无所妨 ^_^
    2. 载入User32.dll需要用到LoadLibrary等,其存在于KERNEL32.DLL中。
    * KERNEL32.DLL是内核模块,无需显式载入。
    3. CreateRemoteThread可以自带一个参数,而LoadLibrary也只需要一个参数,因此可以使用一点点技巧令目标进程载入User32.dll。
    * CreateRemoteThread( , , , &LoadLibraryA, 动态库名称, ,  );
    4. CALL和JMP等指令后面的是相对偏移,因此代码中存在CALL和LONG JMP时需要重新调整相对偏移。
    * CALL指令格式:
    * Y : ……
    * X : CALL Y
    * 生成的指令就是
    * E8, Y-X-5
    * 可见CALL指令跟其所处地址是有关系的,因此将CALL Y移到新地址后要重新计算Y-X-5。
    5. 因为要调整CALL后的相对便宜,因为我使用汇编来编写线程函数。
    * 编译器不对汇编语句进行任何优化和调整
    6. 在DEBUG下,自己定义的函数其函数地址处是个jmp,跳到真正的函数体处,所以不能简单的使用 &函数名称 来得到地址,但如果定义这个全局函数为static可以不生成jmp,可惜这里的代码写在类中,因为还是需要自己去计算真正的地址。
    7. 此处使用"USER32"来令目标进程载入USER32.DLL,这不是一种保稳的做法。保稳的做法是使用全路径,令目标进程无法"作弊" ^_^

    代码如下,没有过多测试
    #include <windows.h>
    #include <cassert>

    class CRemoteEditBox
    {
    public:
        static DWORD GetPIdFromCtrl( HWND hCtrl );
        CRemoteEditBox( DWORD dwRemoteProcessId = 0 );
        ~CRemoteEditBox();
        bool Open( DWORD dwRemoteProcessId );
        void Close();
        bool IsOpen() const;
        int GetTextLength( HWND hEdit ) const;
        bool GetText( HWND hEdit, char* pStr, int nLen ) const;
        bool SetText( HWND hEdit, const char* pStr );
    private:
        static DWORD __stdcall _GetTextLength( LPVOID lpParam );
        static DWORD __stdcall _GetText( LPVOID lpParam );
        static DWORD __stdcall _SetText( LPVOID lpParam );
        static VOID  __stdcall _EndText( LPVOID lpParam );
    private:
        CRemoteEditBox( const CRemoteEditBox& );
        CRemoteEditBox& operator=( const CRemoteEditBox& );
    private:
        DWORD PId;
        HANDLE hProcess;
        mutable void* pData;
        void* pCode;
        HINSTANCE hInst;
        mutable size_t DataLen;
    };

    DWORD CRemoteEditBox::GetPIdFromCtrl( HWND hCtrl )
    {
        DWORD PId = 0;
        GetWindowThreadProcessId( hCtrl, &PId );
        return PId;
    }

    CRemoteEditBox::CRemoteEditBox( DWORD dwRemoteProcessId )
    {
        PId = 0;
        hProcess = 0;
        pData    = 0;
        pCode    = 0;
        hInst    = 0;
        DataLen  = 0;
        Open( dwRemoteProcessId );
    }

    CRemoteEditBox::~CRemoteEditBox()
    {
        Close();
    }

    __declspec(naked) DWORD __stdcall CRemoteEditBox::_GetTextLength( LPVOID lpParam )
    {
        __asm mov eax, [esp+4]
        __asm push eax
        __asm call GetWindowTextLengthA
        __asm ret 4
    }
    __declspec(naked) DWORD __stdcall CRemoteEditBox::_GetText( LPVOID lpParam )
    {
        __asm mov eax, [esp+4]
        __asm push [eax+4]
        __asm add eax, 8
        __asm push eax
        __asm sub eax, 8
        __asm push [eax]
        __asm call GetWindowTextA
        __asm ret 4
    }
    __declspec(naked) DWORD __stdcall CRemoteEditBox::_SetText( LPVOID lpParam )
    {
        __asm mov eax, [esp+4]
        __asm add eax, 4
        __asm push eax
        __asm sub eax, 4
        __asm push [eax]
        __asm call SetWindowTextA
        __asm ret 4
    }
    void __stdcall CRemoteEditBox::_EndText( LPVOID lpParam )
    {
    }
    bool CRemoteEditBox::Open( DWORD dwRemoteProcessId )
    {
        Close();
        if( 0 == dwRemoteProcessId ) return false;

        PId = dwRemoteProcessId;
        hProcess = ::OpenProcess( PROCESS_ALL_ACCESS, TRUE, PId );
        if( 0 != hProcess )
        {
            char USER32[] = "USER32";
            DataLen = 65536;
            pData = VirtualAllocEx( hProcess, 0, DataLen, MEM_COMMIT, PAGE_READWRITE );
            if( 0 != pData )
            {
                WriteProcessMemory( hProcess, pData, USER32, sizeof(USER32), NULL );
                HANDLE hThread = CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)&LoadLibraryA, pData, 0, NULL );
                if( 0 != hThread )
                {
                    WaitForSingleObject( hThread, INFINITE );
                    GetExitCodeThread( hThread, (DWORD*)&hInst );
                    ::CloseHandle( hThread );
                    if( 0 != hInst )
                    {
    #ifdef _DEBUG // DEBUG 下函数多了一个jmp
                        const DWORD __GetTextLength = *(LPDWORD)((LPBYTE)(&_GetTextLength)+1) + (DWORD)(&_GetTextLength) + 5;
                        const DWORD __GetText = *(LPDWORD)((LPBYTE)(&_GetText)+1) + (DWORD)(&_GetText) + 5;
                        const DWORD __SetText = *(LPDWORD)((LPBYTE)(&_SetText)+1) + (DWORD)(&_SetText) + 5;
                        const DWORD __EndText = *(LPDWORD)((LPBYTE)(&_EndText)+1) + (DWORD)(&_EndText) + 5;
    #else
                        const DWORD __GetTextLength = (DWORD)(&_GetTextLength);
                        const DWORD __GetText = (DWORD)(&_GetText);
                        const DWORD __SetText = (DWORD)(&_SetText);
                        const DWORD __EndText = (DWORD)(&_EndText);
    #endif
                        const size_t CODELEN1 = __GetText - __GetTextLength;
                        const size_t CODELEN2 = __SetText - __GetText;
                        const size_t CODELEN3 = __EndText - __SetText;
                        const size_t CODELEN = __EndText - __GetTextLength;

                        pCode = VirtualAllocEx( hProcess, 0, CODELEN, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
                        if( 0 != pCode )
                        {
                            // 重定向
                            char CODE[512];
                            memcpy( CODE, (const void*)__GetTextLength, CODELEN );
                            LPBYTE p = 0;
                            for( p=(LPBYTE)CODE; (BYTE)0xE8!=*p; ++p ); // E8为CALL指令
                            *(DWORD*)(p+1) = (DWORD)&GetWindowTextLength - (DWORD)(p-(LPBYTE)CODE+(LPBYTE)pCode) - 5;
                            for( p=(LPBYTE)CODE+CODELEN1; (BYTE)0xE8!=*p; ++p );
                            for( ++p; (BYTE)0xE8!=*p; ++p );
                            *(DWORD*)(p+1) = (DWORD)&GetWindowText - (DWORD)(p-(LPBYTE)CODE+(LPBYTE)pCode) - 5;
                            for( p=(LPBYTE)CODE+CODELEN1+CODELEN2; (BYTE)0xE8!=*p; ++p );
                            for( ++p; (BYTE)0xE8!=*p; ++p );
                            *(DWORD*)(p+1) = (DWORD)&SetWindowText - (DWORD)(p-(LPBYTE)CODE+(LPBYTE)pCode) - 5;

                            WriteProcessMemory( hProcess, pCode, CODE, CODELEN, NULL);
                            return true;

                            VirtualFreeEx( hProcess, pCode, 0, MEM_RELEASE );
                            pCode = 0;
                        }
                        hThread = CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)&FreeLibrary, hInst, 0, NULL );
                        if( 0 != hThread )
                        {
                            WaitForSingleObject( hThread, INFINITE );
                            ::CloseHandle( hThread );
                        }
                        hInst = 0;
                    }
                }
                VirtualFreeEx( hProcess, pData, 0, MEM_RELEASE );
                pData = 0;
            }
            DataLen = 0;
            CloseHandle( hProcess );
            hProcess = 0;
        }
        PId = 0;
        return false;
    }

    void CRemoteEditBox::Close()
    {
        if( 0 != PId )
        {
            HANDLE hThread = CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)&FreeLibrary, hInst, 0, NULL );
            if( 0 != hThread )
            {
                WaitForSingleObject( hThread, INFINITE );
                ::CloseHandle( hThread );
            }
            hInst = 0;

            VirtualFreeEx( hProcess, pCode, 0, MEM_RELEASE );
            VirtualFreeEx( hProcess, pData, 0, MEM_RELEASE );
            CloseHandle( hProcess );
            PId      = 0;
            hProcess = 0;
            pData    = 0;
            pCode    = 0;
            DataLen  = 0;
        }
    }

    bool CRemoteEditBox::IsOpen() const
    {
        return ( 0 != hProcess );
    }

    int CRemoteEditBox::GetTextLength( HWND hEdit ) const
    {
        assert( IsOpen() );
        assert( GetPIdFromCtrl(hEdit) == PId );

        int ret = 0;
        HANDLE hThread = CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pCode, hEdit, 0, NULL );
        if( 0 != hThread )
        {
            WaitForSingleObject( hThread, INFINITE );
            GetExitCodeThread( hThread, (DWORD*)&ret );
            ::CloseHandle( hThread );
        }
        return ret;
    }

    bool CRemoteEditBox::GetText( HWND hEdit, char* pStr, int nLen ) const
    {
        assert( IsOpen() );
        assert( GetPIdFromCtrl(hEdit) == PId );

        if( sizeof(hEdit)+sizeof(nLen)+nLen+1 >= DataLen )
        {
            DataLen = ( sizeof(hEdit)+sizeof(nLen)+nLen+1 + 65535 )/65536 * 65536;
            VirtualFreeEx( hProcess, pData, 0, MEM_RELEASE );
            pData = VirtualAllocEx( hProcess, 0, DataLen, MEM_COMMIT, PAGE_READWRITE );
            if( 0 == pData )
            {
                DataLen = 0;
                return false;
            }
        }
        WriteProcessMemory( hProcess, pData, &hEdit, sizeof(hEdit), NULL );
        WriteProcessMemory( hProcess, (LPBYTE)pData+sizeof(hEdit), &nLen, sizeof(nLen), NULL );

    #ifdef _DEBUG
        const DWORD __GetTextLength = *(LPDWORD)((LPBYTE)(&_GetTextLength)+1) + (DWORD)(&_GetTextLength) + 5;
        const DWORD __GetText = *(LPDWORD)((LPBYTE)(&_GetText)+1) + (DWORD)(&_GetText) + 5;
    #else
        const DWORD __GetTextLength = (DWORD)(&_GetTextLength);
        const DWORD __GetText = (DWORD)(&_GetText);
    #endif
        int ret = 0;
        LPTHREAD_START_ROUTINE p = (LPTHREAD_START_ROUTINE)( (LPBYTE)pCode + (__GetText-__GetTextLength) );
        HANDLE hThread = CreateRemoteThread( hProcess, NULL, 0, p, pData, 0, NULL );
        if( 0 != hThread )
        {
            WaitForSingleObject( hThread, INFINITE );
            GetExitCodeThread( hThread, (DWORD*)&ret );
            ::CloseHandle( hThread );
            ReadProcessMemory( hProcess, (char*)pData+sizeof(hEdit)+sizeof(nLen), pStr, nLen, NULL );
            return true;
        }
        return false;
    }

    bool CRemoteEditBox::SetText( HWND hEdit, const char* pStr )
    {
        assert( IsOpen() );
        assert( GetPIdFromCtrl(hEdit) == PId );

        size_t nLen = strlen(pStr)+1;
        if( sizeof(hEdit)+nLen+1 >= DataLen )
        {
            DataLen = ( sizeof(hEdit)+nLen+1 + 65535 )/65536 * 65536;
            VirtualFreeEx( hProcess, pData, 0, MEM_RELEASE );
            pData = VirtualAllocEx( hProcess, 0, DataLen, MEM_COMMIT, PAGE_READWRITE );
            if( 0 == pData )
            {
                DataLen = 0;
                return false;
            }
        }
        WriteProcessMemory( hProcess, pData, &hEdit, sizeof(hEdit), NULL );
        WriteProcessMemory( hProcess, (LPBYTE)pData+sizeof(hEdit), (void*)pStr, nLen, NULL );

    #ifdef _DEBUG
        const DWORD __GetTextLength = *(LPDWORD)((LPBYTE)(&_GetTextLength)+1) + (DWORD)(&_GetTextLength) + 5;
        const DWORD __SetText = *(LPDWORD)((LPBYTE)(&_SetText)+1) + (DWORD)(&_SetText) + 5;
    #else
        const DWORD __GetTextLength = (DWORD)(&_GetTextLength);
        const DWORD __SetText = (DWORD)(&_SetText);
    #endif
        int ret = 0;
        LPTHREAD_START_ROUTINE p = (LPTHREAD_START_ROUTINE)( (LPBYTE)pCode + (__SetText-__GetTextLength) );
        HANDLE hThread = CreateRemoteThread( hProcess, NULL, 0, p, pData, 0, NULL );
        if( 0 != hThread )
        {
            WaitForSingleObject( hThread, INFINITE );
            GetExitCodeThread( hThread, (DWORD*)&ret );
            ::CloseHandle( hThread );
            return true;
        }
        return false;
    }

    // 测试代码
    #include <stdio.h>
    int main( void )
    {
        HWND hEdit = (HWND)0x0013047A; // 自己找个EDIT BOX的HANDLE
        CRemoteEditBox a;
        if( a.Open( CRemoteEditBox::GetPIdFromCtrl(hEdit) ) )
        {
            char tmp[260];
            printf( "length = %u\n", a.GetTextLength(hEdit) );
            a.GetText( hEdit, tmp, 260 );
            printf( "str = %s\n\n", tmp );

            a.SetText( hEdit, "A1B2C3" );

            printf( "length = %u\n", a.GetTextLength(hEdit) );
            a.GetText( hEdit, tmp, 260 );
            printf( "str = %s\n\n", tmp );
        }
    }

  • 相关阅读:
    3n+1问题
    判断x的m次方和y的m次方末尾三位数是否相等
    OpenJudge 计算概论1007:点评赛车
    整数划分问题【转】
    证明:平面内有5个整点,必有两个点连线的中点为整点【本资源整理自网络】
    欧几里德算法的证明
    导出本地和远程SVN项目, Export remote SVN repository
    Centos7的firewalld配置
    ESXi5.5下的Centos7虚机配置静态IP
    Dubbo消费端错误: ClassNotFoundException: org.apache.zookeeper.proto.WatcherEvent
  • 原文地址:https://www.cnblogs.com/gisbase/p/1939945.html
Copyright © 2011-2022 走看看