打开一个网页所能用到的常用API有:WinExec,ShellExecute,CreateProcess。但是因为WinExec和CreateProcess都需要指明绝对路径,所以我开始采用的API是ShellExecute,但是ShellExecute有6个参数,这样6次PUSH操作下来,要使用很多的指令才能完成。
后来看到ShellExecute函数还有一个增加的函数版本叫ShellExecuteEx,而且只需要一个参数即可完成,自然就是使用它了。没有增加节,没有改变文件大小,增加了输出表,输入表,重定位表,使用LordPE和UltraEdit完成以上操作。下面是采用过的2种办法。
第1种:12字节,将ShellExecuteEx的参数预先放在数据区,直接调用即可。数据区的布局用数组表示为如下:
//sizeof(SHELLEXECUTEINFO)=0x3c,15个DWORD
DWORD ShellEx[] = {
0x0000003C, //1,cbSize
0x00000000, //2
0x00000000, //3
0x00000000, //4
0x00424a30, //5, lpFile,指向"http://bbs.pediy.com",地址需要重定位;
0x00000000, //6
0x00000000, //7
0x00000000, //8
0x00000000, //9
0x00000000, //10
0x00000000, //11
0x00000000, //12
0x00000000, //13
0x00000000, //14
0x00000000 //15
};
在OpenUrlA函数填充的代码表示如下,实际可能略有不同,还需要重定位:
.text:00401000 sub_401000 proc near ; CODE XREF: _mainp
.text:00401000 68 58 60 40 00 push offset ExecInfo ; lpExecInfo
.text:00401005 FF 15 9C 50 40 00 call ds:ShellExecuteExA
.text:0040100B C3 retn
.text:0040100B sub_401000 endp
第2种:12字节,将参数预先放在数据区,本来是只需要10字节,但是因为使用了ESI寄存器,所以加上必要的头尾后,还是12字节。数据区的布局用数组表示为如下:
//16个DWORD
DWORD ShellEx[] = {
0x00402014, //指向ShellExecuteExA的地址,实际运行时还需要经过重定位。
0x0000003C, //1,cbSize
0x00000000, //2
0x00000000, //3
0x00000000, //4
0x00424a30, //5, lpFile,指向"http://bbs.pediy.com",地址需要重定位;
0x00000000, //6
0x00000000, //7
0x00000000, //8
0x00000000, //9
0x00000000, //10
0x00000000, //11
0x00000000, //12
0x00000000, //13
0x00000000, //14
0x00000000 //15
};
在OpenUrlA函数填充的代码表示如下,实际可能略有不同,还需要重定位:
.text:00401000 sub_401000 proc near ; CODE XREF: _mainp
.text:00401000 56 push esi
.text:00401001 BE 58 60 40 00 mov esi, offset aXA ; "錦ra}<"
.text:00401006 AD lodsd ;取出ShellExecuteExA的地址,ESI->ESI+4
.text:00401007 56 push esi ;此时ESI正好指向函数的参数地址
.text:00401008 FF 10 call [eax] ;调用ShellExecuteExA函数
.text:0040100A 5E pop esi
.text:0040100B C3 retn
.text:0040100B sub_401000 endp
在这里的提交文件中我使用的是第2种方法,经测试可以在2000/XP上正确运行。详见提交的附件。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课