主要思路: hook KiUserExceptionDispatcher 异常处理函数,然后返回到自己的 打开网页 call,OpenUlrA 2个字节就可以搞定,呵呵不知道是否符合题目的要求?

简单说下自己的做法:

1,导出函数OpenUlrA  制造一个异常,这里我用了 CC ,具体汇编代码如下:
000010D0 >    CC            int3
000010D1   .  C3            retn

增加导出表:
对照pe 结构 
148 导出表的地址,14C导出表的大小
在 148 的地方 输入 导出表的地址 21A0 和 大小 45
00000148    A0210000    DD 000021A0          ;  Export Table address = 21A0
0000014C    45000000    DD 00000045          ;  Export Table size = 45 (69.)

然后在  21A0 的地址 对照 导出表格式,进行修改

导出表结构:
typedef struct _IMAGE_EXPORT_DIRECTORY {

Dword Characteristics;

Dword TimeDateStamp;

word MajorVersion;

word MinorVersion;

Dword Name;

Dword Base;

Dword NumberOfFunctions;

Dword NumberOfNames;

Dword AddressOfFunctions; // RVA from base of image

Dword AddressOfNames; // RVA from base of image

Dword AddressOfNameOrdinals; // RVA from base of image

} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;


IMAGE_EXPORT_DIRECTORY 结构成员含义:

Characteristics:此域没有用途,总是为0。

TimeDateStamp:程序被生成的时刻。

MajorVersion/MinorVersion:无实际用途,0。

Name:一个 RVA 值,指向一个 ASCIIZ 字串(dll 名称,如MYDLL.dll)。模块的真实名称。本域是必须的,因为文件名可能会改变。这种情况下,PE装载器将使用这个内部名字。 

Base:基数,加上序数就是函数地址数组的索引值了。 

NumberOfFunctions:模块导出的函数/符号总数。 

NumberOfNames:通过名字导出的函数/符号数目。该值不是模块导出的函数/符号总数,这是由上面的NumberOfFunctions给出。本域可以为0,表示模块可能仅仅通过序数导出。如果模块根本不导出任何函数/符号,那么数据目录中导出表的RVA为0。 

AddressOfFunctions:模块中有一个指向所有函数/符号的RVAs数组,本域就是指向该RVAs数组的RVA。简言之,模块中所有函数的RVAs都保存在一个数组里,本域就指向这个数组的首地址。 

AddressOfNames:类似上个域,模块中有一个指向所有函数名的RVAs数组,本域就是指向该RVAs数组的RVA。

AddressOfNameOrdinals:RVA,指向包含上述 AddressOfNames数组中相关函数之序数的16位数组。 

我修改的导出表:
000021A0  00 00 00 00 A8 76 E3 48 00 00 00 00 D2 21 00 00  ........?..
000021B0  01 00 00 00 01 00 00 00 01 00 00 00 C8 21 00 00  .........?..
000021C0  CC 21 00 00 D0 21 00 00 D0 10 00 00 DC 21 00 00  ?..?..?..?..
000021D0  00 00 70 65 64 69 79 2E 64 6C 6C 00 4F 70 65 6E  ..pediy.dll.Open
000021E0  55 72 6C 41 00 00 00 00 00 00 00 00 00 00 00 00  UrlA............


2.需要的增加导入函数:hook KiUserExceptionDispatcher 需要的 VirtualProtectEx 函数, 异常处理函数 KiUserExceptionDispatcher , 打开网页函数,这里我用 ShellExecuteExA 一个参数, 在这之前,提交了一个用 ShellExecuteExA  的pediy 12 字节

修改导入表:
150 导入表的地址,154导入表的大小 
这里我在150 输入 2028 和 大小 78
00000150    28200000    DD 00002028          ;  Import Table address = 2028
00000154    78000000    DD 00000078          ;  Import Table size = 78 (120.) 

然后在 2028 的地址 对照 导入表格式,进行修改

导入表结构:
typedef struct _IMAGE_IMPORT_DESCRIPTOR {

union {

Dword Characteristics; // 0 for terminating null import descriptor

Dword OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)

};

Dword TimeDateStamp; // 0 if not bound,

// -1 if bound, and real date\time stamp

// in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)

// O.W. date/time stamp of DLL bound to (Old BIND)

Dword ForwarderChain; // -1 if no forwarders

Dword Name;

Dword FirstThunk; // RVA to IAT (if bound this IAT has actual addresses)

} IMAGE_IMPORT_DESCRIPTOR;

IMAGE_IMPORT_DESCRIPTOR 结构成员含义:

结构第一项是一个union子结构。事实上,这个union子结构只是给 OriginalFirstThunk 增添了个别名,您也可以称其为"Characteristics"。该成员项含有指向一个 IMAGE_THUNK_DATA 结构数组的RVA。

TimeDateStamp:程序生成的时刻。此域通常为0。微软的 BIND 程序可以将此 IMAGE_IMPORT_DESCRIPTOR 所对应的dll的生成时刻写到这里来。

ForwarderChain:此域涉及到 forwarding(转交),意味着一个dll 函数在调用另一个 dll。例如,在 WINNT 中,Kernel32.dll 将它的某些输出函数转交给 NTDLL.dll。应用程序可能以为它调用 Kernel32.dll,而事实上它调用的事NTDLL.dll。这个域中含有一个索引,指向 FirstThunk 数组。被这个索引所指定的函数就是一个转交函数。

Name:含有指向DLL名字的RVA,即指向DLL名字的指针,也是一个ASCII字符串。

FirstThunk:与 OriginalFirstThunk 非常相似,它也包含指向一个 IMAGE_THUNK_DATA 结构数组的RVA(当然这是另外一个IMAGE_THUNK_DATA 结构数组)。

我修改的导入表:

00002020 >                                       B0 20 00 00 00 00 00 00          .....
00002030  00 00 00 00 D6 20 00 00 10 20 00 00 B8 20 00 00  ....?.. ..?..
00002040  00 00 00 00 00 00 00 00 34 21 00 00 18 20 00 00  ........4!.. ..
00002050  C0 20 00 00 00 00 00 00 00 00 00 00 5C 21 00 00  ?..........\!..
00002060  20 20 00 00 A0 20 00 00 00 00 00 00 00 00 00 00    ..?..........
00002070  14 21 00 00 00 20 00 00 00 00 00 00 00 00 00 00  !... ..........
00002080  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00002090  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
000020A0  02 21 00 00 F6 20 00 00 E2 20 00 00 00 00 00 00  !..?..?......

3 我hook KiUserExceptionDispatcher 代码:

008B10E0   > \50            push    eax
008B10E1   .  8D4424 00     lea     eax, dword ptr [esp]
008B10E5   .  C74424 00 000>mov     dword ptr [esp], 0
008B10ED   .  50            push    eax                              ; /pOldProtect
008B10EE   .  6A 40         push    40                               ; |NewProtect = PAGE_EXECUTE_READWRITE
008B10F0   .  6A 08         push    8                                ; |Size = 8
008B10F2   .  FF35 20208B00 push    dword ptr [<&NTDLL.KiUserExcepti>; |Address = ntdll.KiUserExceptionDispatcher
008B10F8   .  6A FF         push    -1                               ; |hProcess = FFFFFFFF
008B10FA   .  FF15 08208B00 call    dword ptr [<&KERNEL32.VirtualPro>; \VirtualProtectEx
008B1100   .  837D 0C 01    cmp     dword ptr [ebp+C], 1
008B1104   .  A1 20208B00   mov     eax, dword ptr [<&NTDLL.KiUserEx>
008B1109   .  75 22         jnz     short 008B112D                   ;  判断dll是否释放
008B110B   .  BB C0308B00   mov     ebx, 008B30C0
008B1110   .  8B08          mov     ecx, dword ptr [eax]
008B1112   .  890B          mov     dword ptr [ebx], ecx
008B1114   .  8B48 04       mov     ecx, dword ptr [eax+4]
008B1117   .  894B 04       mov     dword ptr [ebx+4], ecx
008B111A   .  8B1D BC308B00 mov     ebx, dword ptr [8B30BC]          ;  pediy.008B115C
008B1120   .  2BD8          sub     ebx, eax
008B1122   .  83EB 05       sub     ebx, 5
008B1125   .  C600 E9       mov     byte ptr [eax], 0E9              ;  调到自己的Call
008B1128   .  8958 01       mov     dword ptr [eax+1], ebx
008B112B   .  EB 0F         jmp     short 008B113C
008B112D   >  BB C0308B00   mov     ebx, 008B30C0                    ;  dll释放,恢复KiUserExceptionDispatcher 函数头
008B1132   .  8B0B          mov     ecx, dword ptr [ebx]
008B1134   .  8908          mov     dword ptr [eax], ecx
008B1136   .  8B4B 04       mov     ecx, dword ptr [ebx+4]
008B1139   .  8948 04       mov     dword ptr [eax+4], ecx
008B113C   >  8B1C24        mov     ebx, dword ptr [esp]
008B113F   .  50            push    eax                              ; /pOldProtect
008B1140   .  53            push    ebx                              ; |NewProtect
008B1141   .  6A 08         push    8                                ; |Size = 8
008B1143   .  FF35 20208B00 push    dword ptr [<&NTDLL.KiUserExcepti>; |Address = ntdll.KiUserExceptionDispatcher
008B1149   .  6A FF         push    -1                               ; |hProcess = FFFFFFFF
008B114B   .  FF15 08208B00 call    dword ptr [<&KERNEL32.VirtualPro>; \VirtualProtectEx
008B1151   .  58            pop     eax
008B1152   .  C2 0C00       retn    0C

4 自己的代码:

008B115C   .  3D D0108B00   cmp     eax, OpenUrlA                    ;  比较异常地址是否是自己的cc
008B1161      74 12         je      short 008B1175
008B1163   .  8B4C24 04     mov     ecx, dword ptr [esp+4]
008B1167   .  8B1C24        mov     ebx, dword ptr [esp]
008B116A   .  51            push    ecx
008B116B   .  A1 20208B00   mov     eax, dword ptr [<&NTDLL.KiUserEx>
008B1170   .  83C0 08       add     eax, 8
008B1173   .  FFE0          jmp     eax
008B1175   .  68 80308B00   push    008B3080                         ;  执行打开网页的功能
008B117A   .  FF15 18208B00 call    dword ptr [<&SHELL32.ShellExecut>;  SHELL32.ShellExecuteExA
008B1180   .  81C4 F4020000 add     esp, 2F4                         ;  平衡栈返回到调用到OpenUrlA的下一个地址
008B1186   .  C3            retn

5 修改重定位表,需要修改的有 ShellExecuteExA 参数, ShellExecuteExA 函数,KiUserExceptionDispatcher 函数 ,SHELLEXECUTEINFO结构中的 lpVerb和lpFile ,保存 KiUserExceptionDispatcher 函数头的 地址,还有 自己保存自己 call地址, 
重定位表的地址 170 , 大小 50 
00000170    00400000    DD 00004000          ;  Relocation Table address = 4000
00000174    50000000    DD 00000050          ;  Relocation Table size = 50 (80.)

00004000  00 10 00 00 40 00 00 00 03 30 08 30 10 30 2F 30  ...@...000/0
00004010  34 30 83 30 8E 30 96 30 9F 30 BE 30 C5 30 F4 30  40???????
00004020  FC 30 05 31 0C 31 1C 31 2E 31 45 31 4D 31 5D 31  ?1.11.1E1M1]1
00004030  6C 31 76 31 7C 31 00 00 00 00 00 00 00 00 00 00  l1v1|1..........
00004040  00 30 00 00 10 00 00 00 8C 30 90 30 BC 30 00 00  .0.....???..

6 修改到此结束,发了两个附件, pediy12.rar 是 12 个字节 pediy2.rar 是本帖的 2 个字节 
   
   呵呵,第一次写文章,有点乱

上传的附件 TestPediy12.rar
TestPediy2.rar