CreateRemoteThread 错误

竹君子 2004-04-12 12:00:45
我执行如下代码,就会出现windows错误提示关闭应用程序,哪位高手能解答呢:
static DWORD WINAPI MyFunc (LPVOID pData)
{
//do something
MessageBox(0,0,0,0);
//pData输入项可以是任何类型值
//这里我们会传入一个DWORD的值做示例,并且简单返回
return *(DWORD*)pData;
}


static void AfterMyFunc (void)
{
}

void CRemoteThreadTestDlg::OnButtonStart()
{
DWORD PID, TID;
HANDLE hProcess;
char szBuffer[10];
DWORD h;

//步骤2:定位目标进程,这里是一个计算器
//HWND hStart = ::FindWindow( NULL , "未定标题 - 记事本" );


HWND hStart = ::FindWindow (TEXT("SciCalc"),NULL);

//步骤3:获得目标进程句柄,这里用到两个不太常用的函数(当然如果经常做线程/进程等方面的 项目的话,就很面熟了),但及有用

TID = ::GetWindowThreadProcessId (hStart, &PID);

hProcess = OpenProcess(PROCESS_ALL_ACCESS,false,PID);

//步骤4:在目标进程中配变量地址空间,这里我们分配10个字节,并且设定为可以读

//写PAGE_READWRITE,当然也可设为只读等其它标志,这里就不一一说明了。

*(DWORD*)szBuffer=1000;//for test
void *pDataRemote =(char*) VirtualAllocEx( hProcess, 0, sizeof(szBuffer), MEM_COMMIT,

PAGE_READWRITE );

//步骤5:写内容到目标进程中分配的变量空间
::WriteProcessMemory( hProcess, pDataRemote, szBuffer,sizeof(szBuffer),NULL);

//步骤6:在目标进程中分配代码地址空间
//计算代码大小
DWORD cbCodeSize=((LPBYTE) AfterMyFunc - (LPBYTE) MyFunc);
//分配代码地址空间
PDWORD pCodeRemote = (PDWORD) VirtualAllocEx( hProcess, 0, cbCodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE );

//步骤7:写内容到目标进程中分配的代码地址空间
WriteProcessMemory( hProcess, pCodeRemote, &MyFunc, cbCodeSize, NULL);

//步骤8:在目标进程中执行代码

HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) pCodeRemote,pDataRemote, 0 , NULL);

if (hThread)
{
::WaitForSingleObject( hThread, INFINITE );
::GetExitCodeThread( hThread, &h );
TRACE("run and return %d\n",h);
::CloseHandle( hThread );
}
else
{

MessageBox("thread not load successfully!");

}

}
...全文
223 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
竹君子 2004-04-24
  • 打赏
  • 举报
回复
谢谢
magicfound 2004-04-23
  • 打赏
  • 举报
回复
你的错误有两点:
1.函数的大小计算错误。
2.注入的函数中的api函数未定位。

产生原因及解决办法:
1.主程序的release版和debug版,编译的结果不一样。debug时,程序所有函数会在某个地方集中生成 jmp abc 样的指令,(LPBYTE) MyFunc 所指的是这条指令的地址,而函数的真实地址是(LPBYTE) MyFunc + abc 。release时,则没有这样的指令,此时(LPBYTE) MyFunc所指的是真正的函数地址。你的计算方法在release时才是正确的。
2.程序中调用api函数的地方会生成 jmp [abc] 样的指令,而 abc 所指向的是主程序的 iat 。远函数运行到这儿肯定会出错。解决办法是象病毒那样自己定位api函数。

远线程还是用 dll 简单许多。不需要自己定位api。

建议楼主看以下 pe 格式的文档。
竹君子 2004-04-22
  • 打赏
  • 举报
回复
高手指教阿
竹君子 2004-04-15
  • 打赏
  • 举报
回复
我用CreateRemoteThread在一些系统进程上创建,好象没用,不知道怎么才能解决呢
薛定谔之死猫 2004-04-12
  • 打赏
  • 举报
回复
关注
竹君子 2004-04-12
  • 打赏
  • 举报
回复
好象是我引入参数的问题吧,在线程函数中调用的API都不能直接用的
nooning 2004-04-12
  • 打赏
  • 举报
回复
我知道,你写的是某网上用来教学的。

是api问题,你把messagebox去了就对了,

线程地址空间不一样,不可以调用的,一般情况下可以调用kernel32.dll中的函数

最简单的还是直接用LoadLibrary

我编写了三天终于写成了一个IE的HELLO WORLD

但不知道现在能用它做什么?!
Semigod 2004-04-12
  • 打赏
  • 举报
回复
根据我个人的经验
//步骤6:DWORD cbCodeSize=((LPBYTE) AfterMyFunc - (LPBYTE) MyFunc);
中(LPBYTE) AfterMyFunc - (LPBYTE) MyFunc 得到的并不是你所希望的MyFunc的长度!!我以前也遇到过这种问题

下面是我的解决方案
/*
* 这个函数必须非常小心地使用,否则很容易出错。在使用此函数前请仔细
* 检测查你要检测的函数对应的ASM源代码
*
* 这个函数只能检测不包含return语句或只包含最后一句是return语句的函数
*
*/
int CalcSizeOfSimpleFunction(LPVOID pAddr)
{
LPBYTE pAddrNext = (LPBYTE)pAddr;
while (*pAddrNext != 0xC2 // retn 65535
&& *pAddrNext != 0xC3)
pAddrNext++;
int size = pAddrNext - pAddr +1;
// 如果是带清除堆栈返回,则要将清除堆栈的两个字节计算在内
if (* pAddrNext == 0xC2)
size += 2;
return size;
}
halk 2004-04-12
  • 打赏
  • 举报
回复
建立远线程,是要从一个发起进程中将一个线程(代码)注入到宿主进程。不知道楼主说的出现错误的窗口是宿主进程还是发起进程?如果是宿主进程,以上仁兄说的就是最常见的错误。
如果是发起进程,注意到楼主的程序几乎没有做任何调用失败的判断,而是一路走到了CreateRemoteThread。如果前面的几处调用有失败的地方,很可能就会导致程序异常。
PiggyXP 2004-04-12
  • 打赏
  • 举报
回复
应该是远线程的空间计算错误,冲突了宿主进程导致的吧
前言 本程序基于东灿的异常调试模块5.2部分版权信息如下: 1. 该模块功能是补足易错误管理器无法捕捉的异常。 2. 本模块可以截获许多异常,比如内存读写错误,非法汇编指令,算术异常,其他异常等等。 3. 本模块拥有try/catch的异常处理模型,支持多层嵌套,支持向上处理。允许用户自己设定跳过致命异常。 4. 并且支持易原错误管理器接管 5. 建议配合配套工具使用更加好用 正文: 程序原使用模块: 模块名 作者或工作室 用处 高级ApiHookEx 作者未知 HookApi,在模块中用于Hook:CreateRemoteThreadEx和CreateRemoteThread AppThreadVar 作者未知 进程内变量,线程内变量。可以在任意ec模块,任意DLL内调用,全部共享 callstack 作者未知 函数调用堆栈跟踪。 disasm 作者未知 支持MMX/SSE/SSE2/SSE3/3DNow取CPU指令长度 GetThisModuleHandle 作者未知 取出当前ModuleHandle e-try/catch(即new_SEH) 星锋工作室-东灿 SEH结构体等 精简内容 简化模块(即多模块合一,但互相不影响,并且删去了重复的API,数据类型等) 增加注释:对于代码,追加了更多的注释。 部分原理理解(很多都是本人自己的理解,可能不对,若有错误,欢迎指出):AppThreadVar:工作核心:tls线程局部存储(缩写为TLS。进程中的全局变量与函数内定义的静态(static)变量,是各个线程都可以访问的共享变量。在一个线程修改的内存内容,对所有线程都生效。这是一个优点也是一个缺点。说它是优点,线程的数据交换变得非常快捷。说它是缺点,一个线程死掉了,其它线程也性命不保; 多个线程访问共享数据,需要昂贵的同步开销,也容易造成同步相关的BUG。) 部分功能:它主要是为了避免多个线程同时访存同一全局变量或者静态变量时所导致的冲突,尤其是多个线程同时需要修改这一变量时。为了解决这个问题,我们可以通过TLS机制,为每一个使用该全局变量的线程都提供一个变量值的副本,每一个线程均可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每一个线程都完全拥有该变量。而从全局变量的角度上来看,就好像一个全局变量被克隆成了多份副本,而每一份副本都可以被一个线程独立地改变。 用途:动态TLS和静态TLS这两项技术在创建DLL的时候更加有用,这是因为DLL通常并不知道它们被链接到的应用程序的结构是什么样的。1. 如果应用程序高度依赖全局变量或静态变量,那么TLS可以成为我们的救生符。因而最好在开发中最大限度地减少对此类变量的使用,更多的依赖于自动变量(栈上的变量)和通过函数参数传入的数据,因为栈上的变量始终都是与某个特定的线程相关联的。如果不使用此类变量,那么就可以避免使用TLS。2. 但是在编写应用程序时,我们一般都知道自己要创建多少线程,自己会如何使用这些线程,然后我们就可以设计一些替代方案来为每个线程关联数据,或者设计得好一点的话,可以使用基于栈的方法(局部变量)来为每个线程关联数据 TLS分动态和静态,AppThreadVar我认为是动态TLS(调用了TlsAlloc函数) 相当于静态变量(我也只能理解到这里了) ApiHookEx和大部分的APIHook工作原理类似 e-try/catch说实话,这个模块我几乎不能理解原理(能理解的基本上是一些Api,比如MiniDumpWriteDump) 这个可能也是用于捕获异常,而且比较神奇的是,这个捕获到异常以后不会导致程序的退出,而是程序能够正常运行! 可以抛出自定义数值异常,由catch_int/catch_eq_int接收 可以抛出最后一次异常,让上层错误处理器处理 部分实例: try/catch测试:try/catch结果: 部分崩溃代码测试: 结果部分: 程序可以自己写出DMP文件: 更多功能请自己测试!!

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧