我和expression的日与被日 经典分析
程序员文章站
2022-07-07 19:16:27
by jno 2007-11-29 http://www.ph4nt0m.org 当你第一次用expression方式来xss时,你肯定傻眼了,不停弹框,没法关闭...
by jno
2007-11-29
http://www.ph4nt0m.org
当你第一次用expression方式来xss时,你肯定傻眼了,不停弹框,没法关闭浏览器,最终你只能祭出任务管理器将进程结束。也许你其他tab页正有填到一半尚未提交的表单,你就这样被expression给日了,心里非常郁闷,于是就要想办法干它。
很多人第一反应就是cookie,没错这是个好办法:
<div style="width: expression(if(document.cookie.indexof('xxxx')<0){alert(1);document.cookie='xxxx=1;'+document.cookie;})"></div>
不过这样写有个问题,就是被攻击者浏览器只能执行一次你的alert,cookie的作用域大于一次页面执行,适合用来做跨页面的标识,而不是仅仅用来控制一个页面里的某段代码的执行次数,而且你测试起来也挺麻烦,弄得不好就要清cookie。
循着这个思路很自然就会想到在页面里设置标识,于是就有了第二种方法:
<div style="width: expression(if(!window.xxx){alert(1);window.xxx=1;})"></div>
使用全局变量来做标识,使我的代码在这个页面级别只执行一次,这样是一个比较完美的办法,也是目前被使用的最多的办法。
但是到这里总还觉得不爽,虽然我的alert只被执行了一次,但是判断代码还是在被不停的执行,我们还是在被它日,只不过感觉不出来而已了,我们的目标是日它,办法就是执行完我们的代码后删除这条expression,翻阅msdn你很快能找到合适的方法:
object.style.removeexpression(spropertyname)
看起来很美,可是你把这个语句放进expression内部用它来删除expression自身却怎么也不能成功,该死的alert还是会一遍遍的弹出来。使用settimeout延迟执行?失败;使用execscript在全局执行?失败;结合settimeout和execscript在延迟在全局执行?还是失败;在body尾部append一个外部script来执行?失败;在body尾部append一个外部script并且settimeout 延迟并且execscript全局执行?草,终于tmd成功了:
<!------1.htm------>
<html>
<style>
body {
width: expression(eval(string.fromcharcode(0x61,0x6c,0x65,0x72,0x74,0x28,0x31,0x29,0x3b,0x69,0x66,0x28,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x62,0x6f,0x64,0x79,0x29,0x7b,0x76,0x61,0x72,0x20,0x73,0x3d,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x22,0x73,0x63,0x72,0x69,0x70,0x74,0x22,0x29,0x3b,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x62,0x6f,0x64,0x79,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x73,0x29,0x3b,0x73,0x2e,0x73,0x72,0x63,0x3d,0x22,0x31,0x2e,0x6a,0x73,0x22,0x3b,0x7d)));
/*alert(1);if(document.body){var s=document.createelement("script");document.body.appendchild(s);s.src="1.js";}*/
}
</style>
<body>
</body>
</html>
//--------1.js---------//
settimeout(function(){execscript("document.body.style.removeexpression(\"width\")");}, 0);
可是还有那么一点不完美,就是无论怎么样,最少也要执行两次,不过我爽了,总算把这个expression给日了。当然如果你是个完美主义者,可以用这个方法结合if(!window.xxx)法。
各位看官看到这里,可能已经严重怀疑我是被虐狂,这么多方法测试下来,我还不弹框框弹到崩溃?其实我并非浪得虚名,测之前早有准备,先厚者脸皮去幻影邮件列表跪求alert框框原理,没想到大家非常热情地给予帮助,最终zzzevazzz大侠最先找到实现api是messageboxindirectw,从 win2k源代码中觅得。然后又花上半日工夫草成一个hook messageboxindirectw的小工具,可惜又遇到个小问题至今没有解决,这个函数的参数是个msgboxparams结构体:
typedef struct {
uint cbsize;
hwnd hwndowner;
hinstance hinstance;
lpctstr lpsztext;
lpctstr lpszcaption;
dword dwstyle;
lpctstr lpszicon;
dword_ptr dwcontexthelpid;
msgboxcallback lpfnmsgboxcallback;
dword dwlanguageid;
} msgboxparams, *pmsgboxparams;
我写了个小程序测试发现只要把hwndowner和dwstyle都置为0,这个对跨框就不是模态的,父窗口点关闭也可以关闭程序,我hook的目的也在于此,可是在ie里具体测试的时候,发现即使对话框不是模态的,我点关闭ie按钮也没法关闭ie窗口,所以这个方法只针对有tab页的ie7有意义,对话框非模态后,我可以切换到其他tab页去并关闭弹框的tab页,但是对于ie6来说不能点关闭就没有意义,于是我干脆也不修改什么参数了,直接把这个函数返回掉了,代码在最后附上。
至此,我和expression的恩怨总算可以告一段落,整个世界清静了。
/*
* filename: iealertpatch.c
* version: 1.0
* contact: luoluonet@yahoo.cn
* p.s: thanks zzzevazzz, he found out the api that alert uses.
*/
#include <windows.h>
#include <tlhelp32.h>
#include <imagehlp.h>
#pragma comment(lib, "advapi32.lib")
//
// function prototype
//
dword winapi getprocessidbyname(lpctstr lpprocessname);
__inline hookproc();
bool winapi hookalert(dword pid);
lpvoid getsc(lpvoid lpproc, dword* dwlen, dword dwreserved);
//
// start of winmain
//
int apientry winmain(hinstance hinstance, hinstance hpreinstance, lpstr lpcmdline, int ncmdshow)
{
dword pid;
osversioninfoex osvi;
bool bret;
tchar procname[] = text("iexplore.exe");
zeromemory(&osvi, sizeof(osversioninfoex));
osvi.dwosversioninfosize = sizeof(osversioninfoex);
//
// get system version
//
bret = getversionex((osversioninfo *)&osvi);
if (! bret)
{
osvi.dwosversioninfosize = sizeof(osversioninfo);
bret = getversionex((osversioninfo *)&osvi);
if (! bret)
goto freeandexit;
}
// verify if it is nt system
if (osvi.dwplatformid == ver_platform_win32_nt)
{
pid = getprocessidbyname(procname);
if (pid != 0)
hookalert(pid);
}
freeandexit:
return 0;
}
//
// end of winmain
//
//
// @name: getprocessidbyname
// @author: luoluo
// @time: 2005-04-17
// @param: lpprocessname spacifies the processname
// @ret: if success, return the process id
// if failed, return 0
//
dword winapi getprocessidbyname(lpctstr lpprocessname)
{
handle hsnapshot;
dword dwret = 0;
lpprocessentry32 ppe32;
bool bret;
// get all the processes in the snapshot
hsnapshot = createtoolhelp32snapshot(0x00000002, 0);
if (hsnapshot == invalid_handle_value)
{
goto freeandexit;
}
ppe32 = (lpprocessentry32)malloc(sizeof(processentry32));
zeromemory(ppe32, sizeof(processentry32));
ppe32->dwsize = sizeof(processentry32);
// get the first process
bret = process32first(hsnapshot, ppe32);
if (! bret)
{
goto freeandexit;
}
if (stricmp(lpprocessname, ppe32->szexefile) == 0)
{
dwret = ppe32->th32processid;
goto freeandexit;
}
// travesal the left processes
while (true)
{
bret = process32next(hsnapshot, ppe32);
if (! bret)
{
goto freeandexit;
}
if (stricmp(lpprocessname, ppe32->szexefile) == 0)
{
dwret = ppe32->th32processid;
goto freeandexit;
}
}
freeandexit:
if (ppe32 != null) free(ppe32);
if (hsnapshot != null) closehandle(hsnapshot);
return dwret;
}
__inline __declspec(naked) hookproc()
{
__asm
{
leave
retn 4
/*
push esi
mov esi, [ebp+8h]
mov dword ptr [esi+4h], 0h // modify the hwnd
mov dword ptr [esi+14h], 0h // modify the type
pop esi
*/
_emit 90h
_emit 90h
_emit 90h
_emit 90h
}
}
lpvoid getsc(lpvoid lpproc, dword* dwlen, dword dwreserved)
{
lpvoid lpproc1 = null;
lpvoid lpsc = null;
__asm
{
push ebx
mov ebx, lpproc
dec ebx
_loop:
inc ebx
cmp dword ptr [ebx], 90909090h
jne _loop
mov lpproc1, ebx
pop ebx
}
*dwlen = (dword)lpproc1 - (dword)lpproc;
lpsc = malloc(*dwlen + dwreserved);
memset(lpsc, 0, *dwlen + dwreserved);
memcpy(lpsc, lpproc, *dwlen);
*dwlen += dwreserved;
return lpsc;
}
bool winapi hookalert(dword pid)
{
hmodule hmodule = null;
dword dwmessageboxindirectw = 0;
handle hprocess;
handle htoken;
token_privileges tkp;
bool bret = false;
bool bretval;
lpvoid lpcodememory;
memory_basic_information mbi;
size_t szret;
dword dwoldprotect;
dword dwjmpoffset = 0;
unsigned char szjmpcode[5] = {0};
unsigned char szoldcode[5] = {0};
lpvoid lphookcode = null;
dword dwhookcodelen = 0;
hmodule = loadlibrary("user32.dll");
dwmessageboxindirectw = (dword)getprocaddress(hmodule, "messageboxindirectw");
lphookcode = getsc(&hookproc, &dwhookcodelen, 10);
if (lphookcode == null)
{
goto freeandexit;
}
// open process token to ajust privileges
bretval = openprocesstoken(getcurrentprocess(), token_adjust_privileges | token_query, &htoken);
if (! bretval)
{
goto freeandexit;
}
// get the luid for debug privilege
bretval = lookupprivilegevalue(null, se_debug_name, &tkp.privileges[0].luid);
if (! bretval)
{
goto freeandexit;
}
tkp.privilegecount = 1;
tkp.privileges[0].attributes = se_privilege_enabled;
// adjust token privileges
bretval = adjusttokenprivileges(htoken, false, &tkp, sizeof(&tkp), (ptoken_privileges)null, 0);
if (! bretval)
{
goto freeandexit;
}
// open remote process
hprocess = openprocess(process_vm_operation | process_vm_read | process_vm_write | process_query_information, false, pid);
if (hprocess == null)
{
goto freeandexit;
}
// read 5 byte from function to be hooked
bretval = readprocessmemory(hprocess, (lpcvoid)dwmessageboxindirectw, szoldcode, sizeof(szoldcode), null);
if (! bretval)
{
goto freeandexit;
}
// allocate memory from remote process
lpcodememory = virtualallocex(hprocess, null, dwhookcodelen, mem_commit, page_execute_readwrite);
if (lpcodememory == null)
{
goto freeandexit;
}
// query the page information
zeromemory(&mbi, sizeof(memory_basic_information));
szret = virtualqueryex(hprocess, lpcodememory, &mbi, sizeof(memory_basic_information));
if (szret == 0)
{
goto freeandexit;
}
// modify the page protection for write
bretval = virtualprotectex(hprocess, mbi.baseaddress, mbi.regionsize, page_execute_readwrite, &mbi.protect);
if (! bretval)
{
goto freeandexit;
}
// the function has been hooked
if (szoldcode[0] == ((unsigned char)'\xe9'))
{
dwjmpoffset = (*((int*)(szoldcode + 1))) + dwmessageboxindirectw + 5 - ((dword)lpcodememory) - dwhookcodelen + 5;
memcpy(szoldcode + 1, (lpvoid)(&dwjmpoffset), 4);
}
// debugger present and breakpoint here
if (szoldcode[0] == '\xcc')
{
goto freeandexit;
}
// copy the start code of funciton hooked to the end of hook code
memcpy((lpvoid)(((dword)lphookcode) + dwhookcodelen - 10), szoldcode, sizeof(szoldcode));
// code jmp back to function hooked
memset((lpvoid)(((dword)lphookcode) + dwhookcodelen - 5), '\xe9', 1);
dwjmpoffset = dwmessageboxindirectw - ((dword)lpcodememory) - dwhookcodelen + 5;
memcpy((lpvoid)(((dword)lphookcode) + dwhookcodelen - 4), (lpvoid)(&dwjmpoffset), 4);
// write my code to remote process memory
bretval = writeprocessmemory(hprocess, lpcodememory, lphookcode, dwhookcodelen, 0);
if (! bretval)
{
virtualfreeex(hprocess, lpcodememory, dwhookcodelen, mem_release);
goto freeandexit;
}
// modify the page protection to protect
bretval = virtualprotectex(hprocess, mbi.baseaddress, mbi.regionsize, mbi.protect, &dwoldprotect);
if (! bretval)
{
goto freeandexit;
}
// hook code
szjmpcode[0] = '\xe9'; // jmp
dwjmpoffset = ((dword)lpcodememory) - dwmessageboxindirectw - 5;
memcpy(szjmpcode + 1, (lpvoid)(&dwjmpoffset), 4);
// query the page information
zeromemory(&mbi, sizeof(memory_basic_information));
szret = virtualqueryex(hprocess, (lpvoid)dwmessageboxindirectw, &mbi, sizeof(memory_basic_information));
if (szret == 0)
{
goto freeandexit;
}
// modify the page protection for write
bretval = virtualprotectex(hprocess, mbi.baseaddress, mbi.regionsize, page_execute_readwrite, &mbi.protect);
if (! bretval)
{
goto freeandexit;
}
// write hook code to the functon to be hooked
bretval = writeprocessmemory(hprocess, (lpvoid)dwmessageboxindirectw, szjmpcode, sizeof(szjmpcode), 0);
if (! bretval)
{
goto freeandexit;
}
// modify the page protection to protect
bretval = virtualprotectex(hprocess, mbi.baseaddress, mbi.regionsize, mbi.protect, &dwoldprotect);
if (! bretval)
{
goto freeandexit;
}
freeandexit:
if (hprocess != null)
{
closehandle(hprocess);
}
if (htoken != null)
{
closehandle(htoken);
}
if (lphookcode != null)
{
free(lphookcode);
lphookcode = null;
}
return bret;
}
2007-11-29
http://www.ph4nt0m.org
当你第一次用expression方式来xss时,你肯定傻眼了,不停弹框,没法关闭浏览器,最终你只能祭出任务管理器将进程结束。也许你其他tab页正有填到一半尚未提交的表单,你就这样被expression给日了,心里非常郁闷,于是就要想办法干它。
很多人第一反应就是cookie,没错这是个好办法:
<div style="width: expression(if(document.cookie.indexof('xxxx')<0){alert(1);document.cookie='xxxx=1;'+document.cookie;})"></div>
不过这样写有个问题,就是被攻击者浏览器只能执行一次你的alert,cookie的作用域大于一次页面执行,适合用来做跨页面的标识,而不是仅仅用来控制一个页面里的某段代码的执行次数,而且你测试起来也挺麻烦,弄得不好就要清cookie。
循着这个思路很自然就会想到在页面里设置标识,于是就有了第二种方法:
<div style="width: expression(if(!window.xxx){alert(1);window.xxx=1;})"></div>
使用全局变量来做标识,使我的代码在这个页面级别只执行一次,这样是一个比较完美的办法,也是目前被使用的最多的办法。
但是到这里总还觉得不爽,虽然我的alert只被执行了一次,但是判断代码还是在被不停的执行,我们还是在被它日,只不过感觉不出来而已了,我们的目标是日它,办法就是执行完我们的代码后删除这条expression,翻阅msdn你很快能找到合适的方法:
object.style.removeexpression(spropertyname)
看起来很美,可是你把这个语句放进expression内部用它来删除expression自身却怎么也不能成功,该死的alert还是会一遍遍的弹出来。使用settimeout延迟执行?失败;使用execscript在全局执行?失败;结合settimeout和execscript在延迟在全局执行?还是失败;在body尾部append一个外部script来执行?失败;在body尾部append一个外部script并且settimeout 延迟并且execscript全局执行?草,终于tmd成功了:
<!------1.htm------>
<html>
<style>
body {
width: expression(eval(string.fromcharcode(0x61,0x6c,0x65,0x72,0x74,0x28,0x31,0x29,0x3b,0x69,0x66,0x28,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x62,0x6f,0x64,0x79,0x29,0x7b,0x76,0x61,0x72,0x20,0x73,0x3d,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x22,0x73,0x63,0x72,0x69,0x70,0x74,0x22,0x29,0x3b,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x62,0x6f,0x64,0x79,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x73,0x29,0x3b,0x73,0x2e,0x73,0x72,0x63,0x3d,0x22,0x31,0x2e,0x6a,0x73,0x22,0x3b,0x7d)));
/*alert(1);if(document.body){var s=document.createelement("script");document.body.appendchild(s);s.src="1.js";}*/
}
</style>
<body>
</body>
</html>
//--------1.js---------//
settimeout(function(){execscript("document.body.style.removeexpression(\"width\")");}, 0);
可是还有那么一点不完美,就是无论怎么样,最少也要执行两次,不过我爽了,总算把这个expression给日了。当然如果你是个完美主义者,可以用这个方法结合if(!window.xxx)法。
各位看官看到这里,可能已经严重怀疑我是被虐狂,这么多方法测试下来,我还不弹框框弹到崩溃?其实我并非浪得虚名,测之前早有准备,先厚者脸皮去幻影邮件列表跪求alert框框原理,没想到大家非常热情地给予帮助,最终zzzevazzz大侠最先找到实现api是messageboxindirectw,从 win2k源代码中觅得。然后又花上半日工夫草成一个hook messageboxindirectw的小工具,可惜又遇到个小问题至今没有解决,这个函数的参数是个msgboxparams结构体:
typedef struct {
uint cbsize;
hwnd hwndowner;
hinstance hinstance;
lpctstr lpsztext;
lpctstr lpszcaption;
dword dwstyle;
lpctstr lpszicon;
dword_ptr dwcontexthelpid;
msgboxcallback lpfnmsgboxcallback;
dword dwlanguageid;
} msgboxparams, *pmsgboxparams;
我写了个小程序测试发现只要把hwndowner和dwstyle都置为0,这个对跨框就不是模态的,父窗口点关闭也可以关闭程序,我hook的目的也在于此,可是在ie里具体测试的时候,发现即使对话框不是模态的,我点关闭ie按钮也没法关闭ie窗口,所以这个方法只针对有tab页的ie7有意义,对话框非模态后,我可以切换到其他tab页去并关闭弹框的tab页,但是对于ie6来说不能点关闭就没有意义,于是我干脆也不修改什么参数了,直接把这个函数返回掉了,代码在最后附上。
至此,我和expression的恩怨总算可以告一段落,整个世界清静了。
/*
* filename: iealertpatch.c
* version: 1.0
* contact: luoluonet@yahoo.cn
* p.s: thanks zzzevazzz, he found out the api that alert uses.
*/
#include <windows.h>
#include <tlhelp32.h>
#include <imagehlp.h>
#pragma comment(lib, "advapi32.lib")
//
// function prototype
//
dword winapi getprocessidbyname(lpctstr lpprocessname);
__inline hookproc();
bool winapi hookalert(dword pid);
lpvoid getsc(lpvoid lpproc, dword* dwlen, dword dwreserved);
//
// start of winmain
//
int apientry winmain(hinstance hinstance, hinstance hpreinstance, lpstr lpcmdline, int ncmdshow)
{
dword pid;
osversioninfoex osvi;
bool bret;
tchar procname[] = text("iexplore.exe");
zeromemory(&osvi, sizeof(osversioninfoex));
osvi.dwosversioninfosize = sizeof(osversioninfoex);
//
// get system version
//
bret = getversionex((osversioninfo *)&osvi);
if (! bret)
{
osvi.dwosversioninfosize = sizeof(osversioninfo);
bret = getversionex((osversioninfo *)&osvi);
if (! bret)
goto freeandexit;
}
// verify if it is nt system
if (osvi.dwplatformid == ver_platform_win32_nt)
{
pid = getprocessidbyname(procname);
if (pid != 0)
hookalert(pid);
}
freeandexit:
return 0;
}
//
// end of winmain
//
//
// @name: getprocessidbyname
// @author: luoluo
// @time: 2005-04-17
// @param: lpprocessname spacifies the processname
// @ret: if success, return the process id
// if failed, return 0
//
dword winapi getprocessidbyname(lpctstr lpprocessname)
{
handle hsnapshot;
dword dwret = 0;
lpprocessentry32 ppe32;
bool bret;
// get all the processes in the snapshot
hsnapshot = createtoolhelp32snapshot(0x00000002, 0);
if (hsnapshot == invalid_handle_value)
{
goto freeandexit;
}
ppe32 = (lpprocessentry32)malloc(sizeof(processentry32));
zeromemory(ppe32, sizeof(processentry32));
ppe32->dwsize = sizeof(processentry32);
// get the first process
bret = process32first(hsnapshot, ppe32);
if (! bret)
{
goto freeandexit;
}
if (stricmp(lpprocessname, ppe32->szexefile) == 0)
{
dwret = ppe32->th32processid;
goto freeandexit;
}
// travesal the left processes
while (true)
{
bret = process32next(hsnapshot, ppe32);
if (! bret)
{
goto freeandexit;
}
if (stricmp(lpprocessname, ppe32->szexefile) == 0)
{
dwret = ppe32->th32processid;
goto freeandexit;
}
}
freeandexit:
if (ppe32 != null) free(ppe32);
if (hsnapshot != null) closehandle(hsnapshot);
return dwret;
}
__inline __declspec(naked) hookproc()
{
__asm
{
leave
retn 4
/*
push esi
mov esi, [ebp+8h]
mov dword ptr [esi+4h], 0h // modify the hwnd
mov dword ptr [esi+14h], 0h // modify the type
pop esi
*/
_emit 90h
_emit 90h
_emit 90h
_emit 90h
}
}
lpvoid getsc(lpvoid lpproc, dword* dwlen, dword dwreserved)
{
lpvoid lpproc1 = null;
lpvoid lpsc = null;
__asm
{
push ebx
mov ebx, lpproc
dec ebx
_loop:
inc ebx
cmp dword ptr [ebx], 90909090h
jne _loop
mov lpproc1, ebx
pop ebx
}
*dwlen = (dword)lpproc1 - (dword)lpproc;
lpsc = malloc(*dwlen + dwreserved);
memset(lpsc, 0, *dwlen + dwreserved);
memcpy(lpsc, lpproc, *dwlen);
*dwlen += dwreserved;
return lpsc;
}
bool winapi hookalert(dword pid)
{
hmodule hmodule = null;
dword dwmessageboxindirectw = 0;
handle hprocess;
handle htoken;
token_privileges tkp;
bool bret = false;
bool bretval;
lpvoid lpcodememory;
memory_basic_information mbi;
size_t szret;
dword dwoldprotect;
dword dwjmpoffset = 0;
unsigned char szjmpcode[5] = {0};
unsigned char szoldcode[5] = {0};
lpvoid lphookcode = null;
dword dwhookcodelen = 0;
hmodule = loadlibrary("user32.dll");
dwmessageboxindirectw = (dword)getprocaddress(hmodule, "messageboxindirectw");
lphookcode = getsc(&hookproc, &dwhookcodelen, 10);
if (lphookcode == null)
{
goto freeandexit;
}
// open process token to ajust privileges
bretval = openprocesstoken(getcurrentprocess(), token_adjust_privileges | token_query, &htoken);
if (! bretval)
{
goto freeandexit;
}
// get the luid for debug privilege
bretval = lookupprivilegevalue(null, se_debug_name, &tkp.privileges[0].luid);
if (! bretval)
{
goto freeandexit;
}
tkp.privilegecount = 1;
tkp.privileges[0].attributes = se_privilege_enabled;
// adjust token privileges
bretval = adjusttokenprivileges(htoken, false, &tkp, sizeof(&tkp), (ptoken_privileges)null, 0);
if (! bretval)
{
goto freeandexit;
}
// open remote process
hprocess = openprocess(process_vm_operation | process_vm_read | process_vm_write | process_query_information, false, pid);
if (hprocess == null)
{
goto freeandexit;
}
// read 5 byte from function to be hooked
bretval = readprocessmemory(hprocess, (lpcvoid)dwmessageboxindirectw, szoldcode, sizeof(szoldcode), null);
if (! bretval)
{
goto freeandexit;
}
// allocate memory from remote process
lpcodememory = virtualallocex(hprocess, null, dwhookcodelen, mem_commit, page_execute_readwrite);
if (lpcodememory == null)
{
goto freeandexit;
}
// query the page information
zeromemory(&mbi, sizeof(memory_basic_information));
szret = virtualqueryex(hprocess, lpcodememory, &mbi, sizeof(memory_basic_information));
if (szret == 0)
{
goto freeandexit;
}
// modify the page protection for write
bretval = virtualprotectex(hprocess, mbi.baseaddress, mbi.regionsize, page_execute_readwrite, &mbi.protect);
if (! bretval)
{
goto freeandexit;
}
// the function has been hooked
if (szoldcode[0] == ((unsigned char)'\xe9'))
{
dwjmpoffset = (*((int*)(szoldcode + 1))) + dwmessageboxindirectw + 5 - ((dword)lpcodememory) - dwhookcodelen + 5;
memcpy(szoldcode + 1, (lpvoid)(&dwjmpoffset), 4);
}
// debugger present and breakpoint here
if (szoldcode[0] == '\xcc')
{
goto freeandexit;
}
// copy the start code of funciton hooked to the end of hook code
memcpy((lpvoid)(((dword)lphookcode) + dwhookcodelen - 10), szoldcode, sizeof(szoldcode));
// code jmp back to function hooked
memset((lpvoid)(((dword)lphookcode) + dwhookcodelen - 5), '\xe9', 1);
dwjmpoffset = dwmessageboxindirectw - ((dword)lpcodememory) - dwhookcodelen + 5;
memcpy((lpvoid)(((dword)lphookcode) + dwhookcodelen - 4), (lpvoid)(&dwjmpoffset), 4);
// write my code to remote process memory
bretval = writeprocessmemory(hprocess, lpcodememory, lphookcode, dwhookcodelen, 0);
if (! bretval)
{
virtualfreeex(hprocess, lpcodememory, dwhookcodelen, mem_release);
goto freeandexit;
}
// modify the page protection to protect
bretval = virtualprotectex(hprocess, mbi.baseaddress, mbi.regionsize, mbi.protect, &dwoldprotect);
if (! bretval)
{
goto freeandexit;
}
// hook code
szjmpcode[0] = '\xe9'; // jmp
dwjmpoffset = ((dword)lpcodememory) - dwmessageboxindirectw - 5;
memcpy(szjmpcode + 1, (lpvoid)(&dwjmpoffset), 4);
// query the page information
zeromemory(&mbi, sizeof(memory_basic_information));
szret = virtualqueryex(hprocess, (lpvoid)dwmessageboxindirectw, &mbi, sizeof(memory_basic_information));
if (szret == 0)
{
goto freeandexit;
}
// modify the page protection for write
bretval = virtualprotectex(hprocess, mbi.baseaddress, mbi.regionsize, page_execute_readwrite, &mbi.protect);
if (! bretval)
{
goto freeandexit;
}
// write hook code to the functon to be hooked
bretval = writeprocessmemory(hprocess, (lpvoid)dwmessageboxindirectw, szjmpcode, sizeof(szjmpcode), 0);
if (! bretval)
{
goto freeandexit;
}
// modify the page protection to protect
bretval = virtualprotectex(hprocess, mbi.baseaddress, mbi.regionsize, mbi.protect, &dwoldprotect);
if (! bretval)
{
goto freeandexit;
}
freeandexit:
if (hprocess != null)
{
closehandle(hprocess);
}
if (htoken != null)
{
closehandle(htoken);
}
if (lphookcode != null)
{
free(lphookcode);
lphookcode = null;
}
return bret;
}