今天在用vs2010 调试老狼的 gh0st servere端的 dll程序遇到一个问题,首先说下现象:
打开主控端。
server端开启调试。
用一个小exe程序调用dll:
LoadLibrary(".\\..\\..\\bin\\server\\server.dll");
TestRunT pTestRunT=(TestRunT)GetProcAddress(hServerDll,"TestRun");
此时主控端显示上线。
在server端点击桌面管理可以正常显示被控端桌面,然后关闭远程桌面,此时被控端出现一个错误:
TestDll.exe 中的 0x5950cc6f (server.dll) 处有未经处理的异常: 0xC0000005: 读取位置 0x02ecfca4 时发生访问冲突
nRet = m_pClient->Send((LPBYTE)lpData, nSize);
5950CC64 mov eax,dword ptr [ebp+0Ch]
5950CC67 push eax
5950CC68 mov ecx,dword ptr [ebp+8]
5950CC6B push ecx
5950CC6C mov edx,dword ptr [ebp-18h]
5950CC6F mov ecx,dword ptr [edx+4]
此时执行到的指令位置是 5950CC6F
对应的源代码是
int CManager::Send(LPBYTE lpData, UINT nSize)
{
int nRet = 0;
try
{
nRet = m_pClient->Send((LPBYTE)lpData, nSize);
}catch(...){};
return nRet;
}
寄存器edx的数值是
edx 0x02ecfca0 unsigned long
奇怪的是在关闭远程桌面以前这个函数执行了很多次,都没有出现这个问题。现在在关闭远程桌面之后就这样。通过对比发现
出现访问异常的内存 在关闭远程桌面之后数值出现了变化。
可以在关闭远程桌面之后 vs2010下内存访问断点,edx + 4 的位置
调试 -> 新建断点 -> 新建内存断点
此时按F5发现中断在manager类的析构函数里面:
CManager::~CManager()
{
CloseHandle(m_hEventDlgOpen);
}
再看堆栈窗口 是从 Loop_ScreenManager 函数结尾调用而来的:
DWORD WINAPI Loop_ScreenManager(SOCKET sRemote)
{
CClientSocket socketClient;
if (!socketClient.Connect(CKernelManager::m_strMasterHost, CKernelManager::m_nMasterPort))
return -1;
CScreenManager manager(&socketClient);
socketClient.run_event_loop();
return 0;
}
这样就大概分析出执行流程:
在上面函数中定义了一个CScreenManager类的对象manager,这个对象在栈中。CScreenManager基类是 CManager
当在主控端把远程桌面关闭之后run_event_loop 会返回,这样这个函数也就返回了,对象manager也就开始调用自己的析构函数,以前能访问的现在也就不能访问了。 所以就会出现上面的问题。
其实在运行的时候CScreenManager类的构造函数中创建了2个线程ControlThread ,WorkThread
当正常运行没有调试器中断的时候当函数 Loop_ScreenManager 执行完之后ControlThread 这个线程还未完全退出,不知道这样会产生什么意外后果??
经过试验在 函数 Loop_ScreenManager结束之前加入 sleep(20) 可以解决这个问题。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课