一种在注入进程中使用WTL创建无焦点不在任务栏出现“吸附”窗口的方法和思路
最近一直在做沙箱项目,在项目快接近结尾的时候,我想给在我们沙箱中运行的程序界面打上一个标记——标识其在我们沙箱中运行的。我大致想法是:在被注入程序的顶层窗口上方显示一个“标题性”窗口,顶层窗口外框外显示一个“异形”的空心窗口。这些窗口如影子般随着其被“吸附”窗口移动而移动,大小变化而变化。(转载请指明出处)以记事本为被注入程序为例:
我用的注入和HooKApi方案是采用微软的detour库。关于如何HookApi的方法,可以参看我之前的《一种注册表沙箱的思路、实现——Hook Nt函数》。注入的方案,我采用的Detour库的DetourCreateProcessWithDll函数,该函数的W版原型是
BOOL WINAPI DetourCreateProcessWithDllW(LPCWSTR lpApplicationName,__in_z LPWSTR lpCommandLine,LPSECURITY_ATTRIBUTES lpProcessAttributes,LPSECURITY_ATTRIBUTES lpThreadAttributes,BOOL bInheritHandles,DWORD dwCreationFlags,LPVOID lpEnvironment,LPCWSTR lpCurrentDirectory,LPSTARTUPINFOW lpStartupInfo,LPPROCESS_INFORMATION lpProcessInformation,LPCSTR lpDllName,PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW)
该函数从倒数第二个参数之前的全是CreateProcessW的参数,倒数第二个参数是我们要注入的DLL的路径,最后一个参数是真实的CreateProcessW的函数入口地址。该函数的实现细节是:
1 以挂起的方式启动被注入程序
2 在内存中,修改被注入程序的导入表信息,在表中增加一个我们要注入的DLL中的导出函数
3 恢复被挂起的进程
该方案通过修改程序导入表,让系统误以为该程序需要调用到我们要注入的DLL中的导出函数,于是将我们注入的DLL加载到该进程内存空间,从而实现注入。这儿有个细节要说明:该方案要求我们注入DLL要至少有一个导出函数,哪怕这个函数什么也不做。
源码中RegSandBoxMainDialog工程是个MFC工程,它用于启动我们注入的进程并实现注入。我们查看其注入代码的实现
UpdateData(TRUE);char chCurrentPath[MAX_PATH] = {0};GetModuleFileNameA( NULL, chCurrentPath, MAX_PATH );std::string wszCurrentPath = chCurrentPath;size_t nindex = wszCurrentPath.rfind('\\');wszCurrentPath = wszCurrentPath.substr( 0, nindex );wszCurrentPath += "\\";std::string szDllPath = wszCurrentPath;szDllPath += "HookWindow.dll"; // 拼接处注入DLL的完整路径std::wstring wszFilePath = m_Path; // 被注入进程的路径STARTUPINFO StartupInfo;ZeroMemory(&StartupInfo, sizeof(STARTUPINFO));StartupInfo.cb = sizeof(STARTUPINFO);PROCESS_INFORMATION ProcessInfo;ZeroMemory(&ProcessInfo, sizeof(PROCESS_INFORMATION));// FL:使用DetourCreateProcessWithDll需要注入的DLL要有一个导出函数BOOL bSuc = DetourCreateProcessWithDll( wszFilePath.c_str(), NULL, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE ,NULL, NULL, &StartupInfo, &ProcessInfo, szDllPath.c_str(), CreateProcessW );
HookWindow工程编译连接处HookWIndow.dll,我将在之后一步一步介绍这个DLL的编写。
HookWindow是一个Win32 dll工程,我们为其定义一个def文件HookWindow.def,其内容为:
LIBRARY "HookWindow"
EXPORTS Notify
Notify函数是为了达到DetourCreateProcessWithDll要求:注入DLL必须要至少有一个导出函数(原因已在上面说明过)而设计的,实际这个函数什么也没做,他就是个空壳。
VOID Notify(){
}
现在得开始考虑窗口的实现了。我们知道windows系统是消息驱动的模型,那么我们的“吸附”窗口的消息模型该是什么样的?当时我思考方案时得出以下两种方案:
1 Hook进程内窗口消息,在消息链中根据顶层窗口消息而决定我们窗口的创建、显示、隐藏和销毁。这相当于我们窗口的消息循环使用了被注入进程的顶层窗口的消息循环。
2 注入进程后,启动一个线程,该线程负责创建窗口,同时在该线程中再启动一个监视被注入进程顶层窗口的线程,该线程将根据其得到的被注入进程窗口的位置大小状态等信息告诉我们窗口应该做何种处理。
这两种方法各有其优缺点,方法1比方法2少1个线程,但是存在一种场景:当点击被注入程序顶层窗口的非客户区时,我们的窗口会被盖掉,因为这个时候还没轮到我们窗口处理该消息(SetWIndowsHookEx WH_CALLWNDPROCRET),此时我们无法让我们窗口显示在被注入进程顶层窗口前面。方法2就是比方法1多出线程数,如果我想创建两个窗口,就多出两个窗口线程,以此类推。如我设想的需求,我将创建一个管理外框异形空心窗口的线程和一个“标题”窗口,那就多出两个线程。
我觉得我这两个窗口要处理的消息非常简单,同样也想做点与众不同。于是我设计了这样的方案,方案是融合了方案1和方案2的优点:
SetWindowsHookEx勾住被注入进程的消息,同时设置Hook类型为WH_CALLWNDPROCRET。
VOID HookWindowsFn()
{do {g_hhook = SetWindowsHookEx( WH_CALLWNDPROCRET, CallWndRetProc, NULL, GetCurrentThreadId() );if ( NULL == g_hhook ) {_ASSERT(FALSE);}InitializeCriticalSection( &g_cs );} while (0);
}
这样我们将在原程序处理完消息后进行消息处理。
LRESULT CALLBACK CallWndRetProc( __in int nCode, __in WPARAM wParam, __in LPARAM lParam )
{if ( NULL != lParam ) {LPCWPRETSTRUCT lptagCWPRETSTRUCT = (LPCWPRETSTRUCT)lParam;DealMsg( lptagCWPRETSTRUCT->hwnd, lptagCWPRETSTRUCT->message, lptagCWPRETSTRUCT->wParam, lptagCWPRETSTRUCT->lParam );}return CallNextHookEx(NULL, nCode, wParam, lParam);
}
当我们收到消息时,我们要判断是否是我们关心的消息,这样将减少我们处理消息的线程的工作量。
BOOL IsNeedDealMsg( UINT uMsg )
{return ( IsNeedShowMsg( uMsg ) || ( WM_DESTROY == uMsg )|| ( WM_CLOSE == uMsg ) );
}BOOL IsNeedShowMsg( UINT uMsg )
{return ( ( WM_SHOWWINDOW == uMsg )|| ( WM_MOVE == uMsg )|| ( WM_MOVING == uMsg )|| ( WM_SIZE == uMsg )|| ( WM_WINDOWPOSCHANGED == uMsg ) );
}
VOID DealMsg( HWND hAttachedWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{if ( FALSE == IsNeedDealMsg( uMsg ) ) {return;}
其次判断该窗口是否为我们自己创建的“吸附”窗口。如果是我们的“吸附”窗口,我们将不会做任何处理。
VOID DealMsg( HWND hAttachedWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{if ( IsHelperWindow( hAttachedWnd ) ) {return;}
BOOL IsHelperWindow( HWND hwnd )
{WCHAR wszClassNameBuffer[MAX_PATH] = {0};int nClassNameLength = GetClassName( hwnd , wszClassNameBuffer, MAX_PATH - 1 );if ( 0 != nClassNameLength ) {std::wstring wszClassName = wszClassNameBuffer;if ( 0 == wcscmp( wszClassNameBuffer, TITILEWINDOWCLASS ) ||0 == wcscmp( wszClassNameBuffer, OUTSIDEWINDOWCLASS ) ) {return TRUE; // 通过类名判断}}return FALSE;
}
然后我们需要根据消息类型,对窗口句柄做个判断。因为如果我们“宿主”窗口处理完WM_DESTROY后,我们再将不能对其调用GetWindowLong以获取其样式。于是对WM_DESTORY消息,我们只是判断其是否为顶层窗口。如果不是该消息,我们将判断该窗口是否为顶层窗口,且其窗口样式包含WS_SYSMENU(我试验了下,我所遇到的我认为该处理的窗口都有该属性,这个属于经验之谈,不一定准确)。
if ( WM_DESTROY != uMsg ) {if ( FALSE == IsValibleWindow( hAttachedWnd ) ) {return;}}else {if ( FALSE == IsBaseWindow(hAttachedWnd) ) {return;}}if ( FALSE == IsNeedDealMsg( uMsg ) ) {return;}
BOOL IsValibleWindow( HWND hWnd )
{if ( FALSE == IsBaseWindow( hWnd ) ) {return FALSE;}DWORD dwStyle = ::GetWindowLong( hWnd, GWL_STYLE );if ( !( WS_SYSMENU & dwStyle ) ) {return FALSE;}return TRUE;
}BOOL IsTopWindow( HWND hwnd )
{BOOL bTop = FALSE;do {HWND hParentHwnd = NULL;HWND hParenthwnd = GetParent( hwnd );if ( NULL == hParenthwnd ){bTop = TRUE;}} while (0);return bTop;
}BOOL IsBaseWindow( HWND hWnd )
{if ( FALSE == ::IsWindow(hWnd) || FALSE == IsTopWindow(hWnd) ) {return FALSE;}return TRUE;
}
如果是原程序创建的窗口,则判断该句柄是否已经存在一个管理“吸附”窗口的线程(该信息保存在一个Map中)。如果不存在,就创建一个管理两个“吸附”窗口的线程,并将<HWND,HTHREADHANDLE>对保存到Map中。如果存在,则向这个线程管理的窗口发送相应的消息。一个进程可能不止是存在一个顶层窗口,所以我这儿要建立Map信息。
typedef struct _WindowThreadColloction_{LPCWindowThread lpTitleWindowThread;
}WindowThreadColloction, *pWindowThreadColloction;typedef std::map<HWND,WindowThreadColloction> MapHwndThread;
typedef MapHwndThread::iterator MapHwndThreadIter;
LPCWindowThread lpWindowThread = NULL;lpWindowThread = GetTitleWindowThread( hAttachedWnd );if ( NULL == lpWindowThread ) {if ( WM_SHOWWINDOW == uMsg ) {lpWindowThread = new CWindowThread(hAttachedWnd);if ( NULL == lpWindowThread ) {_ASSERT(FALSE);return;}UpdateHwndTitleWindowThread( hAttachedWnd, lpWindowThread );}else {return;}}lpWindowThread->NotifyMsg( uMsg );
}
现在我们将看一下我们管理两个“吸附”窗口的线程类。
class CWindowThread: public CMessageLoop,public CMessageFilter
{
public:CWindowThread(void);~CWindowThread(void);
public:CWindowThread(HWND hAttachWindow);
public:VOID NotifyMsg(UINT uMsg);VOID ExitThread();BOOL PreTranslateMessage(MSG* pMsg);
private:static DWORD WINAPI ThreadRoutine(LPVOID lpParam);
private:HWND m_hAttachWindow;HANDLE m_hThread;CWTLTitleWindow* m_pCWTLTitleWindow;CWTLOutSideWindow* m_pCWTLOutSideWindow;
};
typedef CWindowThread* LPCWindowThread;
消息循环是在该线程中的,于是继承于CMessageLoop;因为我们要让我们窗口屏蔽ATL+F4这类的操作,所以我们要PreTranslateMessage,于是要继承于CMessageFilter。
BOOL CWindowThread::PreTranslateMessage( MSG* pMsg )
{if ( WM_SYSKEYDOWN == pMsg->message ) {return TRUE;}return FALSE;
}
DWORD WINAPI CWindowThread::ThreadRoutine( LPVOID lpParam )
{CWindowThread* pThis = (CWindowThread*) lpParam;if ( NULL == pThis ){return 0xFFFFFFFF;}if ( NULL == pThis->m_pCWTLTitleWindow ) {pThis->m_pCWTLTitleWindow = new CWTLTitleWindow( pThis->m_hAttachWindow );pThis->m_pCWTLTitleWindow->Create( pThis->m_hAttachWindow ); // 注意这儿要设置为父窗口pThis->m_pCWTLTitleWindow->RunWindowMsgLoop();}if ( NULL == pThis->m_pCWTLOutSideWindow ) {pThis->m_pCWTLOutSideWindow = new CWTLOutSideWindow( pThis->m_hAttachWindow );pThis->m_pCWTLOutSideWindow->Create( pThis->m_hAttachWindow ); // 注意这儿要设置为父窗口pThis->m_pCWTLOutSideWindow->RunWindowMsgLoop();}pThis->Run(); // 启动消息循环return 0;
}
VOID CWindowThread::NotifyMsg( UINT uMsg )
{if ( m_pCWTLTitleWindow ){m_pCWTLTitleWindow->DealMsg( uMsg );}if ( m_pCWTLOutSideWindow ) {m_pCWTLOutSideWindow->DealMsg( uMsg );}
}
下面再来看看窗口的实现。因为我们要做的是“吸附”窗口,该窗口应该不能影响原窗口正常的行为(比如不应该抢焦点,不在任务栏出现),同时考虑到刷新问题,我们要让该窗口具有双缓存。以“标题”窗口为例
class CWTLTitleWindow:public CDoubleBufferWindowImpl< CWTLTitleWindow, CWindow, CWinTraits<WS_POPUP|WS_CLIPSIBLINGS, WS_EX_LEFT|WS_EX_LTRREADING|WS_EX_NOPARENTNOTIFY|WS_EX_NOACTIVATE>>
{
public:typedef CWTLTitleWindow _thisClass;typedef CDoubleBufferImpl<_thisClass> _baseDblBufImpl;DECLARE_WND_CLASS_EX(TITILEWINDOWCLASS, CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS, COLOR_WINDOW);CWTLTitleWindow(void);~CWTLTitleWindow(void);
public:CWTLTitleWindow(HWND hAttachWindow);BEGIN_MSG_MAP_EX(CWTLTitleWindow)MESSAGE_HANDLER( WM_SHOWWINDOW, OnShow )MESSAGE_HANDLER( WM_DESTROY, OnDestroy)MESSAGE_HANDLER( WM_QUIT, OnQuit )MESSAGE_HANDLER( WM_MOUSEACTIVATE, OnMouseActive )MESSAGE_RANGE_HANDLER( WM_USER, WM_USER + WM_USER, OnDealUserMsg )CHAIN_MSG_MAP(_baseDblBufImpl)END_MSG_MAP()LRESULT OnShow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);LRESULT OnQuit(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);LRESULT OnMouseActive(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);LRESULT OnDealUserMsg(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);void DoPaint(HDC dc);VOID Start();VOID DealMsg( UINT uMsg );private:ECalcResult CalcTitleWindowXY( int& x, int& y );VOID ShowWindow();
private:HWND m_hAttachHWnd;HINSTANCE m_hInstance;HBITMAP m_hBitmap;RECT m_hAttachWindowRect;
};
首先说一下双缓冲。我继承于CDoubleBufferWindowImpl。在消息映射中,我们要让我们不处理的消息交给基类处理
typedef CWTLTitleWindow _thisClass;typedef CDoubleBufferImpl<_thisClass> _baseDblBufImpl;
CHAIN_MSG_MAP(_baseDblBufImpl)
同时实现DoPaint函数。
void CWTLTitleWindow::DoPaint( HDC dc )
{CRect rc;GetClientRect(&rc); CMemoryDC MemDc( dc, rc );HBRUSH hBitmapBrush = CreatePatternBrush(m_hBitmap);if ( NULL == hBitmapBrush ) {return;}MemDc.FillRect( &rc, hBitmapBrush );DeleteObject( hBitmapBrush );
}
m_bBitmap是我在资源文件中的一个bmp图片,我们在Start函数中将其载入。在类释放时,将其delete。
CWTLTitleWindow::~CWTLTitleWindow(void)
{if ( NULL != m_hBitmap ) {DeleteObject( m_hBitmap );}
}VOID CWTLTitleWindow::Start()
{
#pragma warning(push)
#pragma warning(disable:4312)if ( NULL == m_hInstance ) {m_hInstance = (HINSTANCE)GetWindowLong( GWL_HINSTANCE );}
#pragma warning(pop)if ( NULL == m_hBitmap ) {m_hBitmap = LoadBitmap( m_hInstance, MAKEINTRESOURCE(IDB_BITMAP1));}
}
以上基本上算是完成了双缓冲的操作了,但是为了尽量减少刷新的次数,我会多加个判断:改变的位置和大小是否和现在的位置和大小一致,如果一致则不做任何操作,否则刷新。
ECalcResult CWTLTitleWindow::CalcTitleWindowXY(int& x, int& y )
{ECalcResult eResult = EError;do {RECT rcAttachWindow;if ( FALSE == ::GetWindowRect( m_hAttachHWnd, &rcAttachWindow ) ) {break;}if ( rcAttachWindow.left == m_hAttachWindowRect.left && rcAttachWindow.right == m_hAttachWindowRect.right&& rcAttachWindow.top == m_hAttachWindowRect.top && rcAttachWindow.bottom == m_hAttachWindowRect.bottom ){eResult = ENoChange;break;}else {m_hAttachWindowRect = rcAttachWindow;}x = ( rcAttachWindow.left + rcAttachWindow.right - TIPWINDTH ) / 2;y = rcAttachWindow.top;eResult = ESuc;} while (0);return eResult;
}
再说下无焦点窗口的细节。
首先窗口样式要有WS_POPUP,网上有人说还要加上WS_VISIBLE,但是我觉得没必要。其次扩展属性要有WS_EX_NOACTIVATE。再次我们要处理WM_MOUSEACTIVATE消息。
MESSAGE_HANDLER( WM_MOUSEACTIVATE, OnMouseActive )
LRESULT CWTLTitleWindow::OnMouseActive( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{return MA_NOACTIVATE; // MA_NOACTIVATEANDEAT亦可
}
最后要特别注意下窗口显示和移动对焦点的影响。在窗口显示时,如果我们使用ShowWindow和MoveWindow这类的函数,会导致我们我们窗口还可以获得焦点。我们要使用SetWindowPos,最后一个参数要带上SWP_NOACTIVATE。
VOID CWTLTitleWindow::ShowWindow()
{if ( FALSE == IsBaseWindow( m_hAttachHWnd ) ) {return;}int x = 0; int y = 0;ECalcResult eResult = CalcTitleWindowXY( x, y );if ( EError == eResult ) {::SetWindowPos( m_hWnd, NULL, x, y, TIPWINDTH, TIPHEIGHT, SWP_NOACTIVATE | SWP_HIDEWINDOW );return;}else if ( ENoChange == eResult ) {return;}::SetWindowPos( m_hWnd, NULL, x, y, TIPWINDTH, TIPHEIGHT, SWP_NOACTIVATE | SWP_SHOWWINDOW);
}
最后说一下业务相关的消息传递。在被注入进程的顶层窗口接受到一些消息后,我们会将这些消息传递给我们的窗口,让其做一些处理。为了区分消息来源于顶层窗口还是自己,我将顶层窗口消息处理为一个用户自定义消息。
VOID CWTLTitleWindow::DealMsg( UINT uMsg )
{::PostMessage( m_hWnd, WM_USER + uMsg, NULL, NULL );
}
消息映射是这么写的,用于处理整个用户自定义消息(而不会处理顶层窗口传来的其用户自定义消息)
MESSAGE_RANGE_HANDLER( WM_USER, WM_USER + WM_USER, OnDealUserMsg )
LRESULT CWTLTitleWindow::OnDealUserMsg( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{UINT uAttachedWindowMsg = uMsg - WM_USER;if ( IsNeedShowMsg(uAttachedWindowMsg) ) {ShowWindow();}else {::PostMessage( m_hWnd, uAttachedWindowMsg, wParam, lParam );}return 1;
}
外框窗口和标题窗口基本类似,但是其背景是使用画笔画的,而不是通过贴图。另一个很大的区别就是外框窗口是一个空心的异形窗口。这些区别的主要体现是在DoPaint函数中
void CWTLOutSideWindow::DoPaint( HDC dc )
{CRect rc;GetClientRect(&rc);CMemoryDC MemDc( dc, rc );HRGN RgnInside = CreateRectRgn( rc.left + WIDTHHEIGHTADD, rc.top + WIDTHHEIGHTADD,rc.right - WIDTHHEIGHTADD, rc.bottom - WIDTHHEIGHTADD );HRGN RgnOut = CreateRectRgn( rc.left, rc.top, rc.right, rc.bottom );CombineRgn( RgnOut, RgnOut, RgnInside, RGN_DIFF );MemDc.FillRgn( RgnOut, m_brush );SetWindowRgn( RgnOut, TRUE ); // 设置异形窗口DeleteObject( RgnInside );DeleteObject( RgnOut );
}
这样整个工程OK。以下是源码工程。
源码工程
由于在国内最近不能访问OneDriver,故提供百度云盘的下载链接:http://pan.baidu.com/s/1i39sfdF 密码:rtfa
相关文章:

转:ASP.NET状态保存方法
ASP.NET状态保存分为客户端保存和服务器端保存两种:使用客户端选项存储页信息而不使用服务器资源的这些选项往往具有最低的安全性但具有最快 的服务器性能,因为对服务器资源的要求是适度的。但是,由于必须将信息发送到客户端来进行存储&#…
时至今日,NLP怎么还这么难!
作者 | 刘知远在微博和知乎上关注自然语言处理(NLP)技术的朋友,应该都对#NLP太难了#、#自然语言理解太难了#两个话题标签不陌生,其下汇集了各种不仅难煞计算机、甚至让人也发懵的费解句子或歧义引起的笑话。然而,这些例…
Quartz定时任务学习(四)调度器
org.quartz.Scheduler 类层次 作为一个 Quartz 用户,你要与实现了 org.quartz.Scheduler 接口的类交互。在你调用它的任何 API 之前,你需要知道如何创建一个 Scheduler 的实例。取而代之的是用了某个工厂方法来确保了构造出 Sheduler 实例并正确的得到初…

反汇编算法介绍和应用——线性扫描算法分析
做过逆向的朋友应该会很熟悉IDA和Windbg这类的软件。IDA的强项在于静态反汇编,Windbg的强项在于动态调试。往往将这两款软件结合使用会达到事半功倍的效果。可能经常玩这个的朋友会发现IDA反汇编的代码准确度要高于Windbg,深究其原因,是因为I…

项目计划书的内容
1.引言 1.1计划的目的 1.2项目的范围和目标 1.2.1范围描述 1.2.2主要功能 1.2.3性能 1.2.4管理和技术约束 2.项目估算 2.1使用的历史数据 2.2使用的评估技术 2.3工作量、成本、时间估算 3.风险管理战略 3.1风险识别 3.2有关风险的讨论 3.3风险管理计划 3.3.1风险计划 3.3.2风险…
不用写代码就能学用Pandas,适合新老程序员的神器Bamboolib
作者 | Rahul Agarwal译者 | 陆离编辑 | Jane出品 | AI科技大本营(ID:rgznai100)曾经,你有没有因为学习与使用 Pandas 进行数据检索等操作而感到厌烦过?实现同样的功能,Pandas 给用户提供了很多种方法&…

后海日记(8)
来深圳已经这么长时间了,深圳给我的感觉总体很好,天那么蓝,空气也很清新,总的来说很不错。 努力学习,早日成才。 加油!版权声明:本文为博主原创文章,未经博主允许不得转载。 转载于:…

反汇编算法介绍和应用——递归下降算法分析
上一篇博文我介绍了Windbg使用的线性扫描(linear sweep)反汇编算法。本文我将介绍IDA使用的递归下降(recursive descent)反汇编算法。(转载请指明来源于breaksoftware的csdn博客) 递归(recursiv…
如何快速get到AI工程师面试重点,这12道题必备!
作者 | JP Tech译者 | 刘畅编辑 | Jane出品 | AI科技大本营(ID:rgznai100)【导读】2020 年的三月春招要来了,现在想要 Get 一个算法工程师的实习或全职机会,已经不是一件易事了。如果现在着手复习,茫茫题海…

金邦黑金刚4G内存 VS Vista系统
我的机器配置是 Intel Core 2 4320CPU 金邦黑金刚2G DDR2 800*2 P965P-DS3主板 N 8600GTS 为什么在Vista中 只识别了3.5G 我升级了主版BIOS 主版最高支持8G,哎结果网上一看,才明白。。。现在的系统不是很好的支持4G的内存。…

程序员的量化交易之路(25)--Cointrader之MarketData市场数据实体(12)
转载需注明出处:http://blog.csdn.net/minimicall,http://cloudtrade.top/ 前面一节我们说到了远端事件。其中,市场数据就属于远端事件。市场数据有什么?我们通过代码来回答这个问题: package org.cryptocoinpartners.…
滴滴开源在2019:十大重点项目盘点,DoKit客户端研发助手首破1万Star
整理 | Jane出品 | AI科技大本营(ID;rgznai100)2018 年,科技企业纷纷布局开源战略后迎来的第一个“丰收年”。但对滴滴来说,2019 年才迎来其第一波开源小高潮。自2017年滴滴零星开源数个项目后,滴滴开源项目…

PE文件和COFF文件格式分析——签名、COFF文件头和可选文件头2
之前的博文中介绍了IMAGE_FILE_HEADER结构,现在来讨论比较复杂的“可选文件头”结构体。(转载请指明来自breaksoftware的csdn博客)先看下其声明 typedef struct _IMAGE_OPTIONAL_HEADER {//// Standard fields.//WORD Magic;...DWORD BaseOfData; // not e…

9月第1周安全回顾 IM安全威胁严重 企业增加无线安全投入
本文同时发表在:[url]http://netsecurity.51cto.com/art/200709/55180.htm[/url]本周(0827至0902)安全方面值得关注的新闻集中在安全产品、即时通信安全、无线安全和安全市场。安全产品:Intel vPro技术逐渐升温,关注指…

centos下LAMP之源码编译安装httpd
1 最好先安装组件[rootlocalhost ~]# yum groupinstall additional development [rootlocalhost ~]# yum groupinstall development tool2 安装ap1.5.2r(Apache Portable Runtime),安装apr-util 1.5.4工具[rootlocalhost ~]wget http://mirrors.cnnic.cn/apache//apr/apr-1.5.2…

PE文件和COFF文件格式分析——签名、COFF文件头和可选文件头3
《PE2》中介绍了一些可选文件头中重要的属性,为了全面起见,本文将会讲解那些不是那么重要的属性。虽然不重要,但是还是可以发现很多好玩的情况。首先看一下32位的可选文件头详细定义。(转载请指明来源于breaksoftware的CSDN博客&a…

高效决策的三个关键
“领导者的责任,归纳起来,主要是出主意、用干部两件事。”***的这句话高度概括了领导者的关键任务,而这两件事都有一个共同的核心——决策。决策是管理者的天职,与其说这是他们的权力,不如说是一种责任。每一个经理人&…
开发者都想收藏的深度学习脑图,我们抢先曝光了!
可以看到,通过机器学习技术,软件或服务的功能和体验得到了质的提升。比如,我们甚至可以通过启发式引擎智能地预测并调节云计算分布式系统的节点压力,以此改善服务的弹性和稳定性,这是多么美妙。而对移动平台来说&#…

Cookie 位置_无需整理
为什么80%的码农都做不了架构师?>>> Cookie 位置 C:\Users\admin\AppData\Roaming\Microsoft\Windows\Cookies 转载于:https://my.oschina.net/Majw/blog/464018

PE文件和COFF文件格式分析——节信息
在《PE文件和COFF文件格式分析——签名、COFF文件头和可选文件头3》中,我们看到一些区块的信息都有偏移指向。而我们本文讨论的节信息是没有任何偏移指向的,所以它是紧跟在可选文件头后面的。(转载请注明来源于breaksoftware的csdn博客&#…

强悍!使用Flash和Silverlight制作控件
Silverlight已经发布了正式版本,我也到网站下载了一个并看看,突然发现了他的例子中包含了这个公司。NETiKA TECH。之所以说他强,是因为他尽然使用Flash和Silverlight制作了仿造WinForm的控件,包括:常见的控件ÿ…

《评人工智能如何走向新阶段》后记(再续8)
由AI科技大本营下载自视觉中国2019.12.13 81.近来一波人工智能热潮是在大数据的海量样本及超强计算能力两者支撑下形成的。所以说这一波人工智能是由大数据喂养出来的。这时的机器智能在感知智能和计算智能等一些具体问题上已经达到甚至超越人类水平,目前在语音识别…

Hadoop集群安全性:Hadoop中Namenode单点故障的解决方案及详介AvatarNode
2019独角兽企业重金招聘Python工程师标准>>> 正如大家所知,NameNode在Hadoop系统中存在单点故障问题,这个对于标榜高可用性的Hadoop来说一直是个软肋。本文讨论一下为了解决这个问题而存在的几个solution。 1. Secondary NameNode 原理&#…

PE文件和COFF文件格式分析——RVA和RA相互计算
之前几节一直是理论性质的东西非常多。本文将会讲到利用之前的知识得出一个一个非常有用的一个应用。(转载请指明来源于breaksoftware的csdn博客) 首先我们说下磁盘上A.exe文件和正在内存中运行的A.xe之间的关系。当我们双击A.exe后,A.exe会运…

《评人工智能如何走向新阶段》后记(再续9)
由AI科技大本营下载自视觉中国2019.12.16 96. 近日《Nature》杂志推荐2019年度10大科学进展的杰出论文,其中一篇是有关人工智能的,谈采用深度学习/强化学习算法来训练四足机器狗ANYmal,使它能快速爬起来。该文谈到,在反复训练下&…

RTX组织架构刷新出现了问题
今天发现RTX的组织架构刷新出现了问题。按照网络上的方法什么的把什么配置文件的IP地址改啊改啊。还是没有用。也TELNET了8010端口,也没有用。其实这样的方法之前把服务程序装在另一台机器上倒是可以的。有点麻烦的了。呵呵不知道各位博友有没有解决的好方法啊。呵呵…
一个最简单的通过WireShark破解SSL加密网络数据包的方法
原文地址: http://article.yeeyan.org/view/530101/444688 一般来说,我们用WireShark来抓取包进行分析是没有多大问题的。但这里有个问题是,如果你碰到的是用SSL/TLS等加密手段加密过的网络数据的时候,往往我们只能束手无策。在过…

PE文件和COFF文件格式分析——导出表
在之前的《PE可选文件头》相关博文中我们介绍了可选文件头中很多重要的属性,而其中一个非常重要的属性是(转载请指明来源于breaksoftware的CSDN博客) IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; 该数组保存了…
将Quartz.NET集成到 Castle中
Castle是针对.NET平台的一个开源项目,从数据访问框架ORM到IOC容器,再到WEB层的MVC框架、AOP,基本包括了整个开发过程中的所有东西,为我们快速的构建企业级的应用程序提供了很好的服务.具体可参看TerryLee的Castle 开发系列文章。 …

《评人工智能如何走向新阶段》后记(再续10)
本文由AI科技大本营下载自视觉中国106.百度自研的飞桨(Paddle paddle)框架是中国自研的首个开源产业极人工智能深度学习框架,目前飞桨已累计服务150多万开发者,在定制化训练平台上企业用户超过6.5万,发布了16.9万模型&…