呕心沥血写就(试验代码写了一大坨),修改及转载请标明出处,谢谢!
感谢[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
#include
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
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 );
}
}
阅读(2128) | 评论(13) | 转发(0) |