|
[求助]关于使用Windows钩子将dll注入进程结束相关进程的实现
这个代码中不是写了么,在钩子回调函数中 用::PostQuitMessage(0);我是用这个退出该进程的, 你随便用什么函数退出看自己需要了。 |
|
[求助]关于使用Windows钩子将dll注入进程结束相关进程的实现
利用消息钩子注入dll是很早的事了,我简单建了个工程,简单写了个测试程序,这玩意整的我还注销了一次。 Windows在处理消息时,会先检查是否有钩子挂钩在该消息上,如果没有,就交给程序去处理。如果有钩子在,就调用钩子回调函数,而在检查该钩子的回调函数时,如果,该函数在本程序的进程空间,不管是dll还是exe里,那可以正常访问,如果该函数不在该进程的地址空间,在另一个dll里,那么系统会把该dll映射到该进程的地址空间。再进行后续的处理。 在挂钩消息时,HHOOK SetWindowsHookEx( int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId ); 其中idhook可以选择hook的消息类型,我hook了 WH_GETMESSAGE, lpfn 钩子回调函数,hmod就是回调函数所在的模块, dwthreadid 就是该进程的UI线程。如果为0,那就hook了和该进程在同一桌面环境的所有UI进程。我就是因为这个注销了一次。没桌面了。 首先看下dll的代码: dllmain: HHOOK g_hook = NULL; HMODULE g_hmodule = NULL; LRESULT CALLBACK GetMsgProc(int code, WPARAM wParam, LPARAM lParam); BOOL set_hook(DWORD thread_id ); void un_hook(); BOOL set_hook(DWORD thread_id = 0) { if (g_hook == NULL) g_hook = ::SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hmodule, thread_id); else { un_hook(); g_hook = ::SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hmodule, thread_id); } return (g_hook != NULL); } void un_hook() { if (g_hook != NULL) { ::UnhookWindowsHookEx(g_hook); g_hook = NULL; } } LRESULT CALLBACK GetMsgProc(int code, WPARAM wParam, LPARAM lParam) { ::PostQuitMessage(0); return ::CallNextHookEx(g_hook, code, wParam, lParam); } BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: g_hmodule = hModule; break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } 然后是main.cpp的: #include <iostream> #include <windows.h> using namespace std; typedef BOOL (WINAPI *PFNSET_HOOK)(DWORD thread_id); int main() { HINSTANCE hinstance = NULL; hinstance = ::LoadLibrary(TEXT("InjectDllByHookMessage.dll")); if (hinstance != NULL) { PFNSET_HOOK pfn_set_hook = (PFNSET_HOOK)::GetProcAddress(hinstance, "set_hook"); if (pfn_set_hook == NULL) { ::FreeLibrary(hinstance); cout<<"get set_hook address error"<<endl; return 0; } DWORD thread_id = 0; DWORD process_id = 0; thread_id = ::GetWindowThreadProcessId(::FindWindow(NULL, TEXT("QQ2011")), &process_id); if (pfn_set_hook(thread_id)) cout<<"set hook ok!"<<endl; else cout<<"set hook failed"<<endl; } return 0; } 工程附件: DllInjectByHookMessage.rar |
|
[求助]求教 LINUX下文件数据读取
这个很easy的,可以用系统调用,不带缓存的,先open,然后lseek, 然后read 等 等。 至于这些函数的用法, shell 里 man 2 open 就行 |
|
[求助]远程dll线程资源释放问题
依我的拙见, 首先, 你在dll的DLL_PROCESS_DETACH中作处理没用,系统要退出一个进程时, 会首先结束该进程中运行的线程, 也就是说线程的退出在释放dll前面,这样,当所有的线程退出后,操作系统释放该进程占用的所有资源。 还有就是, 就算后面的test.free不会执行,但是在进程退出后,操作系统会保证释放该进程占用的所有资源,他会为你擦干屁股。这种情况不会造成内存泄漏。这也是操作系统的基本职责。 内存泄漏是指在该进程运行期间,其某项操作申请了内存,而未释放,导致该进程运行期间内存不够,系统会挂掉该进程。 |
|
[求助][求助]windows核心编程里的问题·
线程的控制器参数修改 这个用意各取所需,主要还是用在调试一个进程方面,但是你也可以根据需要,修改,看你的要求了。 |
|
[求助][求助]windows核心编程里的问题·
这个还不简单么,相比上面的线程同步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; } |
|
[求助][求助]windows核心编程里的问题·
楼主啊,我明白你的问题,估计你的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 |
|
[求助][求助]windows核心编程里的问题·
对啊,按照你给的代码, 修改的是当前进程里的一个线程的指令指针,结果线程访问违规了,把进程也挂掉了, 书上所指的远程线程是指 该线程不是在当前进程空间内,而是其他进程的线程,这样就会挂掉其他的进程,这个技术主要是用来做调试用。 还有你的想法,按照你的代码 要是能终止其他的进程就怪了,你一直修改的当前进程里的线程的指令指针。 顺便说下 Windows核心编程(第四版)那本书我翻了N次了, n>5. |
|
[求助][求助]windows核心编程里的问题·
事实证明,加上那句线程是可以恢复的,我的机器上X86 双核,如图: 只是你修改了线程的指令指针,访问违规,挂掉了, 所以你的第一个问题在我这实验时不成立,第二个问题我有点不明白,哪来的远程进程,你是在当前进程环境下创建了一个线程,然后修改了线程的指令指针,他访问了不该访问的地址,操作系统把他家给抄了,所以我觉得你的第二个问题也不成立。 或许是我没明白你的意思,能说详细点么..... |
|
[求助]如何用C++把一段汇编写入另一个程序指定的地址或者是修改运行中程序的指令
恩,你说的对,如果修改了原来的内存属性,确实应该恢复该块内存的属性,内存管理涉及到的问题很多,感谢提醒。 |
|
[求助]新手请教一个注入的问题-取不到正确的函数地址
实践证明,不是 dwCallFrontAddr = (DWORD)GetBuff;这句的问题,是GetBuff函数本身的问题。 我把GetBuff函数改成这样, VOID GetBuff() { ::MessageBox(NULL, TEXT("getbuff function"),TEXT("aaa"),MB_OK); //char *Tar = NULL; //_asm //{ // mov Tar, edi; //} //Log(Tar); //_asm //{ // mov ebx, 0x401480; // call ebx; //} } 效果如图: OD效果如图: 完整的代码如下: mycode.rar 顺便说下我用的vs2008 工程文件做了转换,打开原来的就行 |
|
[求助]如何用C++把一段汇编写入另一个程序指定的地址或者是修改运行中程序的指令
呵呵,我明白楼主的意思了。 首先,来说说你改后的代码,VirtualProtect这个函数用的不对,你要修改的是另一个进程的内存地址,而这个函数是修改当前调用进程的内存的,换VirtualProtectEx,就行。 其次,你的意思是把某处内存的地址换成你自己的汇编指令,就不能把汇编指令写在函数里,再用WriteProcessMemery来写函数地址,这样,WriteProcessMemery在该内存处写的只是一个jmp指令,就 是跳到函数的执行处,因为这个函数名称单独来用就相当于一个指针,所以按照你的方法,即使修改成功了,该地址处只是一个jmp指令,跳到函数的执行口,而不是mov指令。 我给出我的解决方法吧。我测试成功了。 有什么问题可以去bbs.virusest.net找我。 首先,在OD里看一下程序的这个0x0041324A地址是否有效,如图,其内容如图所示。 在来看修改后的。如图 具体的实现代码如下,我就不多说了: #include <stdio.h> #include <windows.h> const PCHAR gameCaption="SomeApp"; //mov eax, eax //mov eax,eax char shellcode[] = {0x8B,0xC0,0x8B,0xC0}; BOOL TestFunc() { int iCount = 1024; DWORD dwNumberOfBytes = 0; DWORD dwProcessID = 0; LPVOID mFunc = CallSelectMonster; BOOL fOk = FALSE; HANDLE hProcess = NULL; HANDLE hThread = NULL; LPVOID ThreadAddr = NULL; __try { HWND hGame = ::FindWindowA(NULL, gameCaption); ::GetWindowThreadProcessId(hGame, &dwProcessID); hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID); if (hProcess == NULL) __leave; MEMORY_BASIC_INFORMATION mbi = {0}; if (!::VirtualQueryEx(hProcess, (LPVOID)0x0041324A, &mbi, sizeof(mbi)) == sizeof(mbi)) { DWORD dwError = ::GetLastError(); __leave; } //这里看下内存的属性,如果是已提交的,就修改保护属性,否则还得在分配,保留,提交... if (mbi.State == MEM_COMMIT) { DWORD dwOldProtect = 0; if (!::VirtualProtectEx(hProcess, (LPVOID)0x0041324A, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &dwOldProtect)) { DWORD dwError = ::GetLastError(); __leave; } } else { ThreadAddr = ::VirtualAllocEx(hProcess, (LPVOID)0x0041324A, iCount, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (ThreadAddr == NULL) { //如果分配失败了,那么由操作系统自己找内存,在来一次 DWORD i = ::GetLastError(); ThreadAddr = VirtualAllocEx(hProcess, NULL, iCount, MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE); if (ThreadAddr == NULL) { printf("error of virtualallocex: %d",::GetLastError()); __leave; } } } BOOL bWrite = ::WriteProcessMemory(hProcess, (LPVOID)0x0041324A, shellcode, sizeof(shellcode), &dwNumberOfBytes); if (!bWrite) { printf("error of writeprocessmemory: %d",::GetLastError()); __leave; } //hThread = ::CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)ThreadAddr, NULL, 0, 0); //if (hThread == NULL) //{ // printf("error of createremotethread: %d", ::GetLastError()); // __leave; //} //::WaitForSingleObject(hThread, INFINITE); fOk = TRUE;//到了这里,everything is ok... } __finally { if (hProcess != NULL) { ::CloseHandle(hProcess); } } return fOk; } int main() { if (TestFunc()) printf("ok!"); else printf("failed!"); getchar(); return 0; } |
|
[求助]如何用C++把一段汇编写入另一个程序指定的地址或者是修改运行中程序的指令
刚才望了说了,我看楼主的代码是在MFC下写的,并且是在主线程里调用了等待函数,赶紧改了吧,要么重启一个线程执行含有waitforsingleobject, 要么就换 MsgWaitForMultipleObjects 否则你的 线程会切入内核状态(堵塞住),窗口无法接受消息,界面假死。 |
|
[求助]如何用C++把一段汇编写入另一个程序指定的地址或者是修改运行中程序的指令
楼主的代码的问题很多, 我是第一次在看雪发帖,说说我的看法,如有错误,请指正。谢之。 首先,看这个函数: LPVOID ThreadAdd = VirtualAllocEx(hProcess,(LPVOID)0x0041324A,n,MEM_COMMIT,PAGE_EXECUTE_READWRITE); 第一,你的 内存地址是硬编码为0x0041324A,而在进程空间内,这段内存的状态未知,是保留状态还是已提交状态,不能确定,而msdn上对这个函数的allocationtype参数解释时明确说明: The function fails if you attempt to commit a page that has not been reserved. The resulting error code is ERROR_INVALID_ADDRESS. 假如这个内存地址的没被保留的话,你直接MEM_COMMIT会导致函数失败。给这个参数建议传递MEM_COMMIT | MEM_RESERVE 并且检查返回值。 或者给内存地址传递NULL值,那么系统将在该进程空间内自动寻找一块你所要求的大小的内存。并将其属性修改。 第二,逻辑混乱,你在将数据写入进程空间后,为什么要接着来个virtualfreeex函数,首先这个函数会执行失败,再者,就算该函数执行成功了,那你后面的线程肯定执行不了任何的代码,因为这句之后该块的内存会变为free状态,线程是没法执行代码的。看看sdk中是怎么说的: If a page is released, its state changes to free, and it is available for subsequent allocation operations. After memory is released or decommitted, you can never refer to the memory again. Any information that may have been in that memory is gone forever. Attempts to read from or write to a free page results in an access violation exception. If you need to keep information, do not decommit or free memory that contains the information. 在将该块内存release之后,你将决(never)不能再次引用该内存,任何该内存区域的信息都将消失。而且是forever的消失,任何尝试读或者写的操作都将会导致访问违规。 再来说该函数的参数传递,你在讲MEM_REALSE传递进去后,那个内存块大小的参数必须为0,sdk中说了 是 must be,并且内存地址必须为virtualallocex函数返回的地址。 后面的代码就不多说了,我自己重新写了一遍你的函数,如有错误,望指正。 const PCHAR gameCaption="ADD"; void CallSelectMonster (long MonsterSn) { _asm{ mov eax,eax mov eax,eax } } BOOL TestFunc() { int iCount = 1024 * 5; DWORD dwNumberOfBytes = 0; DWORD dwProcessID = 0; LPVOID mFunc = CallSelectMonster; BOOL fOk = FALSE; HANDLE hProcess = NULL; HANDLE hThread = NULL; LPVOID ThreadAddr = NULL; __try { HWND hGame = ::FindWindowA(NULL, gameCaption); ::GetWindowThreadProcessId(hGame, &dwProcessID); hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID); if (hProcess == NULL) __leave; ThreadAddr = ::VirtualAllocEx(hProcess, (LPVOID)0x0041324A, iCount, MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE); if (ThreadAddr == NULL) { //如果分配失败了,那么由操作系统自己找内存,在来一次 ThreadAddr = VirtualAllocEx(hProcess, NULL, iCount, MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE); if (ThreadAddr == NULL) { printf("error of virtualallocex: %d",::GetLastError()); __leave; } } BOOL bWrite = ::WriteProcessMemory(hProcess, ThreadAddr, mFunc, iCount, &dwNumberOfBytes); if (!bWrite) { printf("error of writeprocessmemory: %d",::GetLastError()); __leave; } hThread = ::CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)ThreadAddr, NULL, 0, 0); if (hThread == NULL) { printf("error of createremotethread: %d", ::GetLastError()); __leave; } ::WaitForSingleObject(hThread, INFINITE); fOk = TRUE;//到了这里,everything is ok... } __finally { if (hProcess != NULL) { if (hThread != NULL) { ::VirtualFreeEx(hProcess, ThreadAddr, 0, MEM_RELEASE); ::CloseHandle(hThread); } ::CloseHandle(hProcess); } } return fOk; } |
|
[下载]各种 编程语言教程+黑客教程+入侵提权
这些网上到处都是,腻了 |
操作理由
RANk
{{ user_info.golds == '' ? 0 : user_info.golds }}
雪币
{{ experience }}
课程经验
{{ score }}
学习收益
{{study_duration_fmt}}
学习时长
基本信息
荣誉称号:
{{ honorary_title }}
能力排名:
No.{{ rank_num }}
等 级:
LV{{ rank_lv-100 }}
活跃值:
在线值:
浏览人数:{{ visits }}
最近活跃:{{ last_active_time }}
注册时间:{{ user_info.create_date_jsonfmt }}
勋章
兑换勋章
证书
证书查询 >
能力值