首页
社区
课程
招聘
[旧帖] [求助][求助]windows核心编程里的问题· 0.00雪花
发表于: 2011-4-4 13:39 1736

[旧帖] [求助][求助]windows核心编程里的问题· 0.00雪花

2011-4-4 13:39
1736
#include "stdafx.h"
DWORD WINAPI ThreadProc(LPVOID lpParam);
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
   // TODO: Place code here.
CONTEXT Context;
DWORD dwThreadId;
HANDLE hThread;

hThread = CreateThread(
          NULL,         //默认安全属性
          NULL,         //默认堆栈大小
          ThreadProc,   //线程入口地址(执行线程的函数)
          NULL,         //传给函数的参数
          0,            //指定线程立即执行
          &dwThreadId   //返回线程的ID号
          );
        
if (SuspendThread(hThread)==0xFFFFFFFF)

                     {

                              MessageBox(NULL,TEXT("麻痹!!!"),TEXT("错误i"),0);

                     }

                     else

                     {

                         MessageBox(NULL,TEXT("Suspend thread is ok.") ,TEXT(""),0);

                     }

Context.ContextFlags = CONTEXT_FULL;//去掉这一句就能恢复线程!!
if(GetThreadContext(hThread,&Context))
{
  MessageBox(NULL,TEXT("huoquchenggong"),TEXT(""),0);

}
Context.Eip = 0x00010000;
SetThreadContext(hThread,&Context);

   if (ResumeThread(hThread)==0xFFFFFFFF)

                     {

                          MessageBox(NULL,TEXT("Resume no!!"),TEXT("错误i"),0);

                     }

                     else

                     {

                         MessageBox(NULL,TEXT("Resume thread is ok!"),TEXT(""),0);

                     }

  return 0;
}

DWORD WINAPI ThreadProc(LPVOID lpParam)
{
  int x,y ,i;
  MessageBox(NULL,TEXT("ZOU DAOXIANCHENG"),TEXT(""),0);
   for (i=0;i<5;i++)

       {

             x++;
       y++;

              Sleep(2000);

       }

  //帐号再拷贝到全局变量字符串g_strusername里。。
  return 1;
}

Context.ContextFlags = CONTEXT_FULL;//去掉这一句就能恢复线程!!
加上总是恢复不了挂起的线程·也不知道为什么··只是帮Eip 的指令指针改了一下而已·
(1)加上总是恢复不了挂起的线程·也不知道为什么··?

(2)(Eip 的指令指针改了一下)为什么当线程重新恢复运行时加入的内存地址上的远程进程为什么不会终止·
这是windows核心编程上说" 当Eip跳到别的应用程序的地址上的时候·此时远程进程会异常退出"
很想知道????难道新的地址Eip指向的地址没?还是 ???

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 0
支持
分享
最新回复 (14)
雪    币: 692
活跃值: (40)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
2
事实证明,加上那句线程是可以恢复的,我的机器上X86 双核,如图:


只是你修改了线程的指令指针,访问违规,挂掉了,

所以你的第一个问题在我这实验时不成立,第二个问题我有点不明白,哪来的远程进程,你是在当前进程环境下创建了一个线程,然后修改了线程的指令指针,他访问了不该访问的地址,操作系统把他家给抄了,所以我觉得你的第二个问题也不成立。

或许是我没明白你的意思,能说详细点么.....
上传的附件:
  • 1.jpg (39.54kb,188次下载)
2011-4-4 14:32
0
雪    币: 81
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
在windows核心编程里有一句话···“随便修改线程的EIP地址,这可能造成远程线程的访问违规,系统会先向用户显示一个未处理的异常消息框,然后终止远程进程(所谓远程进程指的应该是改动过的EIP的新位置的所在进程)。被终止的是远程线程,而不是我们的进程。我们自己继续正常执行的同时,可以成功的使另一个进程崩溃”找是原话。。。。
但是代码在我的机器上跑··就运行的好好的·但是没有任何异常终止其他的进程···很奇怪··
2011-4-6 20:01
0
雪    币: 81
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
看你跑找段程序好像是·因为违规而终止自己的应用程序··找和windows核心编程所述不符哈···
也不知道是出了什么问题了··
2011-4-6 20:14
0
雪    币: 692
活跃值: (40)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
5
对啊,按照你给的代码, 修改的是当前进程里的一个线程的指令指针,结果线程访问违规了,把进程也挂掉了, 书上所指的远程线程是指 该线程不是在当前进程空间内,而是其他进程的线程,这样就会挂掉其他的进程,这个技术主要是用来做调试用。

还有你的想法,按照你的代码 要是能终止其他的进程就怪了,你一直修改的当前进程里的线程的指令指针。

顺便说下  Windows核心编程(第四版)那本书我翻了N次了, n>5.
2011-4-7 09:21
0
雪    币: 692
活跃值: (40)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
6
楼主啊,我明白你的问题,估计你的CPU是单核的,所以运行你的代码什么也没显示。
我早上在公司的单核奔4上运行时,也是什么反应都没,后来想了想,我知道什么原因了。
你的代码在双核CPU上执行,没什么问题,就是 我上面的那张图。但是在单核CPU上执行,就涉及到系统的线程调度问题,有点麻烦。 当主线程创建完线程二后线程二不一定会得到CPU,主线程的CPU时间片还没用完就退出了程序,所以线程二得不到运行。所以什么反应都没。而你要确保的就是在主线程退出之前,在单CPU上,线程二有机会得到CPU。这样才能测试出异常。
      下面我写了一个专门针对单核CPU的代码,这个代码可以测试出该异常的产生。测试环境是XP sp3 奔四单核。

    假设你对系统的线程调度和同步有一定的了解。程序运行,首先创建一个人工重置事件,状态为未通知。 然后创建一个线程,我称为线程二。 线程二一开始就等待该事件的通知,而主线程创建完线程二后就通知该事件,让堵塞的线程二跑起来,线程二运行会弹出一个messagebox,说这是在线程二运行。 然后主线程 会重置该人工重置事件,将其设为未通知状态,并且等待该事件,此时主线程堵塞住,而当线程二的messagebox返回后,线程二把该事件设置为通知状态,线程二继续等待该事件,堵塞住,而此时主线程收到了线程二的通知,挂起线程二的线程,并且设置其控制寄存器的指令指针为0x00010000,然后在resume线程二,主线程等待线程二的结束。 然而线程二被resume时其指令指针被修改为违法值,其会产生一个访问违规的异常,设置一个结构化异常处理,捕获该异常,并将控制权交给线程二,打印一些信息后 退出。

程序的运行结果如图:



#include <iostream>
#include <windows.h>
#include <process.h>
#include <excpt.h>

int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep) ;


unsigned  __stdcall ThreadFunc(void * pArguments)
{
	
	__try
	{
		 HANDLE hevent = (HANDLE)pArguments;

		 DWORD wait_result = WaitForSingleObject(hevent, INFINITE);
		 if (wait_result == WAIT_OBJECT_0)
		 {
			 
			 ::MessageBox(NULL, TEXT("second thread was running...."), TEXT("second thread"), MB_OK);
			 //如果messagebox返回,则系统重新唤醒线程二,当线程收到消息时,系统会唤醒该线程处理消息
			 ::SetEvent(hevent);//在这里通知主线程,你可以挂起我了....
			 ::WaitForSingleObject(hevent, INFINITE);

		 }
	
	}
	__except(filter(GetExceptionCode(), GetExceptionInformation()))
	{
		
		MessageBox(NULL, TEXT("handling exception..."), TEXT("except"), MB_OK);
	}
	
	return 0;//normal exit...
}


int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep) 
{

	if (code == EXCEPTION_ACCESS_VIOLATION) 
	{
      printf("EXCEPTION_ACCESS_VIOLATION catched!...\n");
	  printf("the exception address: %x\n", ep->ExceptionRecord->ExceptionAddress);
	  printf("the exception flags: %0x\n", ep->ExceptionRecord->ExceptionFlags);
	  printf("the exception information: %0x\n", ep->ExceptionRecord->ExceptionInformation);
      return EXCEPTION_EXECUTE_HANDLER;//返回这个表明线程二知道异常的产生,我自己能处理,控制权交给我

    }
    else 
	{

      return EXCEPTION_CONTINUE_SEARCH;//向上回滚,此时运行库捕获该异常,意味着该程序要挂了,

    }

}



int main()
{
	unsigned thread_id = 0;
	HANDLE hthread = NULL;
	CONTEXT context;
	context.ContextFlags = CONTEXT_FULL; //使用context之前必须得初始化该参数
    HANDLE hevent = NULL;
	__try
	{
		hevent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
		if (hevent == NULL)
		{
			printf("Create event error: %d",::GetLastError());
			__leave;
		}

		hthread = (HANDLE) _beginthreadex(NULL, 0, &ThreadFunc, (void *)hevent, 0, &thread_id);
		if (hthread == NULL)
		{
			printf("beginthreadex error: %d\n",::GetLastError());
			__leave;
		}

		::SetEvent(hevent);//让线程二弹messagebox
		::Sleep(0);//放弃主线程的剩余时间片,让第二个线程得到CPU,不能省,否则线程二得不到CPU,不能弹出messagebox
		::ResetEvent(hevent);//将事件设置成未通知的状态,这句的执行是在线程二弹出messagebox之后,此时,线程二堵塞住,主线程得到CPU
		
		::WaitForSingleObject(hevent, INFINITE);//主线程等待线程二的通知,主线程堵塞,线程二得到CPU
		if (::SuspendThread(hthread) == (DWORD)-1)
		{
			printf("suspendthread error: %d\n", ::GetLastError());
			__leave;
		}

		printf("suspend thread ok!\n");

		if (!::GetThreadContext(hthread, &context))
		{
			printf("getthreadcontext error: %d\n",::GetLastError());
			__leave;
		}

		printf("getthread context success!\n");

		context.Eip = 0x00010000;//这句将刚创建的线程的指令指针修改,会导致访问违规

		if (!::SetThreadContext(hthread, &context))
		{
			printf("setthreadcontext error: %d\n", ::GetLastError());
			__leave;
		}

		printf("setthread context success!\n");

		if (::ResumeThread(hthread) == (DWORD)-1)
		{
			printf("resume thread error: %d\n",::GetLastError());
			__leave;
		}

		printf("resume thread ok!\n");

		
		//::Sleep(3000);
		if (WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0)
		{
			printf("the second thread exit... now in main thread..\n");
		}
		


	}	
	__finally
	{
		if (hthread != NULL)
			::CloseHandle(hthread);
	}


	return 0;
}

如果感觉上面的布局乱,工程代码如下:
test.rar
上传的附件:
2011-4-7 13:52
0
雪    币: 81
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
ls例子代码·简单明了·非常感谢。。
就是还有一个小问题不太明白··
你说我一直修改的线程EIP是本进程的··你能不能再举个例子把EIP的地址指向另外一个进程。。
使得另外一个进程异常退出··我不知道是不是需要开启远程线程,,还是直接将EIP的地址修改到一个要结束的进程地址呢?????????初学者很多问题·请你见谅哈·
2011-4-7 17:25
0
雪    币: 81
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
最好能再帮我举个例子·说明我上面的问题····谢谢你··
2011-4-7 17:26
0
雪    币: 692
活跃值: (40)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
9
这个还不简单么,相比上面的线程同步easy多了,代码如下,我拿QQ开刀,效果如图所示:


可以看到异常的原因和我上面的本机单核测试的异常原因是一样的。

代码如下:
int main()
{
	
	HANDLE hthread = NULL;
	CONTEXT context;
	context.ContextFlags = CONTEXT_FULL;
	__try
	{

		HWND hwnd = ::FindWindow(NULL, TEXT("QQ2011"));
		if (hwnd == NULL)
			__leave;
		DWORD process_id = 0;
		DWORD thread_id = 0;
		thread_id = GetWindowThreadProcessId(hwnd, &process_id);
		
		hthread = ::OpenThread(THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME, FALSE, thread_id);
		if (hthread == NULL)
		{
			printf("openThread error: %d\n", ::GetLastError());
			__leave;
		}

		if (::SuspendThread(hthread) == (DWORD)-1)
		{
			printf("SuspendThread error:%d\n", ::GetLastError());
			__leave;
		}

		if (!::GetThreadContext(hthread, &context))
		{
			printf("getThreadcontext errror:%d\n",::GetLastError());
			__leave;
		}

		context.Eip = 0x00010000;
		
		if (!::SetThreadContext(hthread, &context))
		{
			printf("setthreadcontext error:%d\n", ::GetLastError());
			__leave;
		}

		if (::ResumeThread(hthread) == (DWORD)-1)
		{
			printf("resume thread error:%d\n", ::GetLastError());
			__leave;
		}


		
	}
	__finally
	{
		if (hthread != NULL)
			::CloseHandle(hthread);
	}

	return 0;

}
上传的附件:
2011-4-7 18:13
0
雪    币: 81
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
就是把远程的线程的EIP设置成一个违规的地址·远程进程就会结束了哈····我明白了··

我一直是以为“把本进程的线程的EIP设置成别的进程的地址·别的进程就结束了哈··”  ,看来不是这样的哈··

总之非常的感谢LS。。。。
2011-4-8 15:19
0
雪    币: 81
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
最后一个问题···那设置远程线程的EIP到底对一个程序来说··有什么的用意呢··
就是设置线程的EIP到底有什么用?????
2011-4-8 15:22
0
雪    币: 692
活跃值: (40)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
12
线程的控制器参数修改 这个用意各取所需,主要还是用在调试一个进程方面,但是你也可以根据需要,修改,看你的要求了。
2011-4-8 19:45
0
雪    币: 109
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
这个贴技术~~
2011-4-10 12:17
0
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
Make~留用备查
2012-8-14 11:07
0
雪    币: 4
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
最近也在看windows核心编程,发现还是要动动手才能体会的更深啊
2012-8-15 22:07
0
游客
登录 | 注册 方可回帖
返回
//