发新话题
打印

[原创]逆向分析并重组源码的过程

[原创]逆向分析并重组源码的过程

文章作者:asm
信息来源:邪恶八进制信息安全团队

   又屈服在goldberg的淫威下了。麻痹,一提到此人我就性趣勃勃。或许是他给俺力量,刚和他聊完,就怀上了这篇文章,由此可见,goldberg的能力之强。废话少说了,文章开始临盆。
复制内容到剪贴板
代码:
.text:0001045A
.text:0001045A ; Attributes: bp-based frame
.text:0001045A
.text:0001045A         public start
.text:0001045A start      proc near
.text:0001045A         push  ebp ;很多时候,我们把push 一个数据作为一个
;函数的参数对待。但是push也可以保存临时值。

.text:0001045B         mov   ebp, esp    ; 把esp保存到ebp中去,开始进入函数体
.text:0001045D         push  offset s_PI   ; "驱动入口\r\n"
.text:00010462         call  DbgPrint    ; 格式化输出
.text:00010462
.text:00010467         add   esp, 4     ; 堆栈由函数自己清除
.text:0001046A         call  sub_10260    ; 调用一个子函数
.text:0001046A
.text:0001046F         call  sub_10309    ; 调用一个子函数
.text:0001046F
.text:00010474         call  sub_10397    ; 调用一个子函数
.text:00010474
.text:00010479         push  offset asc_1068C ; "执行完退出\r\n\r\n"
.text:0001047E         call  DbgPrint    ; 函数执行完毕
.text:0001047E
.text:00010483         add   esp, 4     ; 这里和上面一样,C的规则,由函数自己清空堆栈。汇编和C都沿用stdcall,必须这样
.text:00010486         mov   eax, 0C0000182h ; 这里是驱动程序的返回,即 mov eax,STATUS_DEVICE_CONFIGURATION_ERROR
.text:0001048B         leave
.text:0001048C         retn  8
.text:0001048C
.text:0001048C start      endp
这里,我们已经构造出整个程序的结构。即:格式化打印信息-----分别调用三个子函数-------程序返回。这样一来,就可以重组出这个代码的框架:
复制内容到剪贴板
代码:
.386
.model flat, stdcall
option casemap:none
;
;这里包含用到的头文件和库。具体是哪个,还得进一步分析这个程序到底有到哪些函数

.data?
.
.data
.
.const

.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING

Invoke DbgPrint,CTXT(“驱动入口”)

call  sub_10260 ;调用第一个子函数,姑且这么写
call  sub_10309
call  sub_10397

Invoke DbgPrint,CTXT(“程序结束”)
mov eax,STATUS_DEVICE_CONFIGURATION_ERROR
ret
DriverEntry endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end DriverEntry
就像建筑一栋大楼,把主干已经弄好,现在轮到添枝加叶。先看第一个子函数sub_10260。这里直接call调用了,所以就不存在任何参数传递。
复制内容到剪贴板
代码:
.text:00010260 sub_10260    proc near     
.text:00010260
.text:00010260 Handle     = dword ptr -24h ; 参数定义。如果是正的,就是局部变量
.text:00010260 IoStatusBlock  = _IO_STATUS_BLOCK ptr -20h ;参数。这里IDA也已经给出结构
.text:00010260 ObjectAttributes= OBJECT_ATTRIBUTES ptr -18h
.text:00010260
.text:00010260         push  ebp
.text:00010261         mov   ebp, esp
.text:00010263         add   esp, 0FFFFFFDCh
.text:00010266         push  ds:off_10538
.text:0001026C         push  offset Format  ; "创建目录: %ws \r\n"
.text:00010271         call  DbgPrint    ; %ws是Unicode,在内核中是使用Unicode
.text:00010271
.text:00010276         add   esp, 8
.text:00010279         lea   ecx, [ebp+ObjectAttributes] ; 初始化OBJ_CASE_INSENSITIV
.text:0001027C         mov   dword ptr [ecx], 18h
.text:00010282         and   dword ptr [ecx+4], 0
.text:00010286         mov   dword ptr [ecx+0Ch], 240h
.text:0001028D         and   dword ptr [ecx+10h], 0
.text:00010291         mov   dword ptr [ecx+8], offset asc_10534 ; " \""
.text:00010298         and   dword ptr [ecx+14h], 0
.text:0001029C         push  0        ; EaLength
.text:0001029E         push  0        ; EaBuffer
.text:000102A0         push  21h       ; CreateOptions
.text:000102A2         push  3        ; CreateDisposition
.text:000102A4         push  0        ; ShareAccess
.text:000102A6         push  80h       ; FileAttributes
.text:000102AB         push  0        ; AllocationSize
.text:000102AD         lea   eax, [ebp+IoStatusBlock]
.text:000102B0         push  eax       ; IoStatusBlock
.text:000102B1         lea   eax, [ebp+ObjectAttributes]
.text:000102B4         push  eax       ; ObjectAttributes
.text:000102B5         push  100000h     ; DesiredAccess
.text:000102BA         lea   eax, [ebp+Handle]
.text:000102BD         push  eax       ; FileHandle
.text:000102BE         call  ZwCreateFile  ; 打开。内核中创建目录,
                            ;创建文件都使用这个函数
.text:000102BE
.text:000102C3         or   eax, eax    ; 返回值是否成功
.text:000102C5         jnz   short loc_102F9 ; 不成功就跳到这里,
                            ;恰恰它格式化的代码已经提示我们,
                            ;目录创建失败
.text:000102C5
.text:000102C7         cmp   [ebp+IoStatusBlock.Information], 2 ; 这里查看文件的属性。
                                     ;2代表FILE_CREATED
.text:000102CB         jnz   short loc_102DC ; 跳到 loc_102DC
.text:000102CB
.text:000102CD         push  offset s_I   ; "目录创建\r\n"
.text:000102D2         call  DbgPrint
.text:000102D2
.text:000102D7         add   esp, 4     ; 恢复堆栈
.text:000102DA         jmp   short loc_102EF ; 目录创建之后,就要关闭句柄
.text:000102DA
.text:000102DC ; ---------------------------------------------------------------------------
.text:000102DC
.text:000102DC loc_102DC:            
.text:000102DC         cmp   [ebp+IoStatusBlock.Information], 1 ; 测试文件的FILE_OPENED                                      ;属性。很明显,是.if--                                      ;-.elseif--.endif的结构
.text:000102E0         jnz   short loc_102EF
.text:000102E0
.text:000102E2         push  offset s_KJ   ; "目录共享\r\n"
.text:000102E7         call  DbgPrint
.text:000102E7
.text:000102EC         add   esp, 4
.text:000102EC
.text:000102EF
.text:000102EF loc_102EF:              
.text:000102EF                    
.text:000102EF         push  [ebp+Handle]  ; Handle
.text:000102F2         call  ZwClose     ; 两个属性测试完毕,目录才真正创建成功~!
.text:000102F2
.text:000102F7         jmp   short locret_10307 ; 函数返回
.text:000102F7
.text:000102F9 ; ---------------------------------------------------------------------------
.text:000102F9
.text:000102F9 loc_102F9:              
.text:000102F9         push  eax
.text:000102FA         push  offset s_IIAI08x ; "无法创建目录,错误代码 %08X\r\n"
.text:000102FF         call  DbgPrint
.text:000102FF
.text:00010304         add   esp, 8
.text:00010304
.text:00010307
.text:00010307 locret_10307:            
.text:00010307         leave          ; 程序返回
.text:00010308         retn
.text:00010308
.text:00010308 sub_10260    endp
首先这个子函数初始化OBJ_CASE_INSENSITIV结构。这个结构是这样的:
ObjectAttributes OBJECT_ATTRIBUTES<?>。接着打印要创建的目录名。代码:

.const
CCOUNTED_UNICODE_STRING "\\??\\c:\\fuck", g_usDirName, 4
.
.
invoke DbgPrint, $CTA0("\创建目录: %ws \n"), g_usDirName.Buffer

在创建目录后同时测试其属性,分别打印。下面是重组的代码:
复制内容到剪贴板
代码:
CreateDirectory proc
local oa:OBJECT_ATTRIBUTES
local iosb:IO_STATUS_BLOCK
local hDirectory:HANDLE
;------------------------------------------------------------
;Unicode格式化输出目录名。在内核使用Unicode
;------------------------------------------------------------
invoke DbgPrint, $CTA0("创建目录: %ws "), g_usDirName.Buffer
  ;------------------------------------------------------------
; 初始化OBJ_CASE_INSENSITIVE,oa作为参数传递给ZwCreateFile
;------------------------------------------------------------
InitializeObjectAttributes addr oa, addr g_usDirName, \
   OBJ_CASE_INSENSITIVE + OBJ_KERNEL_HANDLE, NULL, NULL   
invoke ZwCreateFile, addr hDirectory, SYNCHRONIZE, addr oa, addr iosb, 0, FILE_ATTRIBUTE_NORMAL, \
   0, FILE_OPEN_IF, FILE_DIRECTORY_FILE + FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0
.if eax == STATUS_SUCCESS
;------------------------------------------------------------
;文件创建属性
;------------------------------------------------------------
.if iosb.Information == FILE_CREATED
  invoke DbgPrint, $CTA0("目录创建")
;------------------------------------------------------------
;文件共享属性   
;------------------------------------------------------------
.elseif iosb.Information == FILE_OPENED
  invoke DbgPrint, $CTA0("目录共享")
.endif
invoke ZwClose, hDirectory
.else
;------------------------------------------------------------
;格式化输出,创建目录失败!
;------------------------------------------------------------
invoke DbgPrint, $CTA0("无法创建目录,错误代码 %08X"), eax
.endif
ret
CreateDirectory endp
现在来看第二个子函数sub_10309。
复制内容到剪贴板
代码:
.text:00010309 sub_10309    proc near        
.text:00010309
.text:00010309 Handle     = dword ptr -24h  ;函数句柄
.text:00010309 IoStatusBlock  = _IO_STATUS_BLOCK ptr -20h ;IO_STATUS_BLOCK结构
.text:00010309 ObjectAttributes= OBJECT_ATTRIBUTES ptr -18h ;OBJECT_ATTRIBUTES结构
.text:00010309
.text:00010309         push  ebp
.text:0001030A         mov   ebp, esp
.text:0001030C         add   esp, 0FFFFFFDCh
.text:0001030F         push  ds:off_1050C
.text:00010315         push  offset s_IWs_0 ; "创建文件 %ws \r\n"
.text:0001031A         call  DbgPrint    ; 这段代码很熟悉吧 :)
.text:0001031A
.text:0001031F         add   esp, 8
.text:00010322         lea   ecx, [ebp+ObjectAttributes] ; 这段是不是也很熟悉 :)
.text:00010325         mov   dword ptr [ecx], 18h
.text:0001032B         and   dword ptr [ecx+4], 0
.text:0001032F         mov   dword ptr [ecx+0Ch], 240h
.text:00010336         and   dword ptr [ecx+10h], 0
.text:0001033A         mov   dword ptr [ecx+8], offset s_24 ; "24"
.text:00010341         and   dword ptr [ecx+14h], 0
.text:00010345         push  0        ; EaLength
.text:00010347         push  0        ; EaBuffer
.text:00010349         push  20h       ; CreateOptions
.text:0001034B         push  2        ; CreateDisposition
.text:0001034D         push  0        ; ShareAccess
.text:0001034F         push  80h       ; FileAttributes
.text:00010354         push  0        ; AllocationSize
.text:00010356         lea   eax, [ebp+IoStatusBlock]
.text:00010359         push  eax       ; IoStatusBlock
.text:0001035A         lea   eax, [ebp+ObjectAttributes]
.text:0001035D         push  eax       ; ObjectAttributes
.text:0001035E         push  100000h     ; DesiredAccess
.text:00010363         lea   eax, [ebp+Handle]
.text:00010366         push  eax       ; FileHandle
.text:00010367         call  ZwCreateFile  ; 刚多说了,创建目录和创建文件都使用这个
.text:00010367
.text:0001036C         or   eax, eax
.text:0001036E         jnz   short loc_10387
.text:0001036E
.text:00010370         push  offset s_IJ   ; "文件创建成功\r\n"
.text:00010375         call  DbgPrint    ; 他已经提示我们文件创建成功了
.text:00010375
.text:0001037A         add   esp, 4
.text:0001037D         push  [ebp+Handle]  ; Handle
.text:00010380         call  ZwClose     ; 关闭句柄
.text:00010380
.text:00010385         jmp   short locret_10395 ; 交还控制权
.text:00010385
.text:00010387 ; ---------------------------------------------------------------------------
.text:00010387
.text:00010387 loc_10387:              
.text:00010387         push  eax
.text:00010388         push  offset s_IZAI08x ; "文件创建失败,错误代码: %08X\r\n"
.text:0001038D         call  DbgPrint
.text:0001038D
.text:00010392         add   esp, 8     ; 清除堆栈
.text:00010392
.text:00010395
.text:00010395 locret_10395:            
.text:00010395         leave          ; 每一个程序的最后都要把控制权交给主程序
.text:00010396         retn
.text:00010396
.text:00010396 sub_10309    endp
和创建目录的一样,创建文件也是初始化OBJECT_ATTRIBUTES,调用ZwCreateFile。下面是源码:
复制内容到剪贴板
代码:
CreateFile proc
local oa:OBJECT_ATTRIBUTES
local iosb:IO_STATUS_BLOCK
local hFile:HANDLE
;-----------------------------------------------------------
;
;格式化输出创建的文件名。在内核中使用Unicode
;Buffer缓冲区保存着文件路径
;
;-----------------------------------------------------------
invoke DbgPrint, $CTA0("创建文件 %ws "), g_usFileName.Buffer
;-----------------------------------------------------------
  ;初始化OBJ_CASE_INSENSITIVE结构
  ;-----------------------------------------------------------
InitializeObjectAttributes addr oa, addr g_usFileName, \
   OBJ_CASE_INSENSITIVE + OBJ_KERNEL_HANDLE, NULL, NULL
;-----------------------------------------------------------   
  ;打开文件
  ;-----------------------------------------------------------
invoke ZwCreateFile, addr hFile, SYNCHRONIZE, addr oa, addr iosb, 0, FILE_ATTRIBUTE_NORMAL, \
   0, FILE_CREATE, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0
.if eax == STATUS_SUCCESS
invoke DbgPrint, $CTA0("文件创建成功")
invoke ZwClose, hFile
.else
invoke DbgPrint, $CTA0("文件创建失败,错误代码: %08X"), eax
.endif
ret
CreateFile endp
最后一个子函数sub_10397
复制内容到剪贴板
代码:
.text:00010397 sub_10397    proc near   
.text:00010397
.text:00010397 Handle     = dword ptr -24h
.text:00010397 IoStatusBlock  = _IO_STATUS_BLOCK ptr -20h
.text:00010397 ObjectAttributes= OBJECT_ATTRIBUTES ptr -18h
.text:00010397
.text:00010397         push  ebp
.text:00010398         mov   ebp, esp
.text:0001039A         add   esp, 0FFFFFFDCh
.text:0001039D         push  offset s_KI   ; "打开文件准备写入数据\r\n"
.text:000103A2         call  DbgPrint
.text:000103A2
.text:000103A7         add   esp, 4
.text:000103AA         lea   ecx, [ebp+ObjectAttributes]
.text:000103AD         mov   dword ptr [ecx], 18h
.text:000103B3         and   dword ptr [ecx+4], 0
.text:000103B7         mov   dword ptr [ecx+0Ch], 240h
.text:000103BE         and   dword ptr [ecx+10h], 0
.text:000103C2         mov   dword ptr [ecx+8], offset s_24 ; "24"
.text:000103C9         and   dword ptr [ecx+14h], 0
.text:000103CD         push  0        ; EaLength
.text:000103CF         push  0        ; EaBuffer
.text:000103D1         push  20h       ; CreateOptions
.text:000103D3         push  1        ; CreateDisposition
.text:000103D5         push  1        ; ShareAccess
.text:000103D7         push  0        ; FileAttributes
.text:000103D9         push  0        ; AllocationSize
.text:000103DB         lea   eax, [ebp+IoStatusBlock]
.text:000103DE         push  eax       ; IoStatusBlock
.text:000103DF         lea   eax, [ebp+ObjectAttributes]
.text:000103E2         push  eax       ; ObjectAttributes
.text:000103E3         push  100002h     ; DesiredAccess
.text:000103E8         lea   eax, [ebp+Handle]
.text:000103EB         push  eax       ; FileHandle
.text:000103EC         call  ZwCreateFile  ; 打开我们刚创建的文件
.text:000103EC
.text:000103F1         or   eax, eax
.text:000103F3         jnz   short loc_1044A ; 无法写入文件
.text:000103F3
.text:000103F5         push  offset s_KJ_0  ; "文件打开成功\r\n"
.text:000103FA         call  DbgPrint
.text:000103FA
.text:000103FF         add   esp, 4
.text:00010402         push  0        ; Key
.text:00010404         push  0        ; ByteOffset
.text:00010406         push  4Dh       ; Length
.text:00010408         push  offset Buffer  ; "这里是文件的内容"
.text:0001040D         lea   eax, [ebp+IoStatusBlock]
.text:00010410         push  eax       ; IoStatusBlock
.text:00010411         push  0        ; ApcContext
.text:00010413         push  0        ; ApcRoutine
.text:00010415         push  0        ; Event
.text:00010417         push  [ebp+Handle]  ; FileHandle
.text:0001041A         call  ZwWriteFile   ; 写入数据。
.text:0001041A
.text:0001041F         or   eax, eax
.text:00010421         jnz   short loc_10432
.text:00010421
.text:00010423         push  offset s_IJ_0  ; "文件写入成功\r\n"
.text:00010428         call  DbgPrint
.text:00010428
.text:0001042D         add   esp, 4
.text:00010430         jmp   short loc_10440
.text:00010430
.text:00010432 ; ---------------------------------------------------------------------------
.text:00010432
.text:00010432 loc_10432:              
.text:00010432         push  eax
.text:00010433         push  offset s_IIAI08x_0 ; "无法写入文件,错误代码: %08X\r\n"
.text:00010438         call  DbgPrint
.text:00010438
.text:0001043D         add   esp, 8
.text:0001043D
.text:00010440
.text:00010440 loc_10440:               
.text:00010440         push  [ebp+Handle]  ; Handle
.text:00010443         call  ZwClose
.text:00010443
.text:00010448         jmp   short locret_10458
.text:00010448
.text:0001044A ; ---------------------------------------------------------------------------
.text:0001044A
.text:0001044A loc_1044A:              
.text:0001044A         push  eax
.text:0001044B         push  offset s_IKAI08x ; "无法打开文件,错误代码: %08X\r\n"
.text:00010450         call  DbgPrint
.text:00010450
.text:00010455         add   esp, 8
.text:00010455
.text:00010458
.text:00010458 locret_10458:              ;提交控制权
.text:00010458         leave
.text:00010459         retn
.text:00010459
.text:00010459 sub_10397    endp
到此,三个未知的子函数已经逐一逆向出源码。程序的流程我们已经很清楚---创建目录----创建文件----写入数据到文件。现在整理一下得出完整代码:
复制内容到剪贴板
代码:
;-----------------------------------------------
;
;code by asm
;QQ 448761813
;
;-----------------------------------------------
.386
.model flat, stdcall
option casemap:none
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
include w2k\ntstatus.inc
include w2k\ntifs.inc
include w2k\ntoskrnl.inc
includelib ntoskrnl.lib
include Strings.mac
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;利用宏定义文件路径和目录,还可以这样做:
;g_usFileName dw &#39;\&#39;,&#39;?&#39;,&#39;?&#39;,&#39;c&#39;,&#39;:&#39;,&#39;\&#39;,&#39;F&#39;,&#39;i&#39;,&#39;l&#39;,&#39;e&#39;,&#39;W&#39;,&#39;o&#39;,&#39;r&#39;,&#39;k&#39;,&#39;s&#39;,&#39;\&#39;,&#39;t&#39;,&#39;e&#39;,&#39;s&#39;,&#39;t&#39;,&#39;.&#39;,&#39;t&#39;,&#39;x&#39;,&#39;t&#39;,0
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
.const
CCOUNTED_UNICODE_STRING "\\??\\c:\\fuck\\test.txt", g_usFileName, 4
CCOUNTED_UNICODE_STRING "\\??\\c:\\fuck", g_usDirName, 4
;CTA0 "fuck the world", g_szData,4
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
.code
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;创建目录函数                       
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
CreateDirectory proc
local oa:OBJECT_ATTRIBUTES
local iosb:IO_STATUS_BLOCK
local hDirectory:HANDLE
;------------------------------------------------------------
;Unicode格式化输出目录名。在内核使用Unicode
;------------------------------------------------------------
invoke DbgPrint, $CTA0("创建目录: %ws "), g_usDirName.Buffer
  ;------------------------------------------------------------
; 初始化OBJ_CASE_INSENSITIVE,oa作为参数传递给ZwCreateFile
;------------------------------------------------------------
InitializeObjectAttributes addr oa, addr g_usDirName, \
   OBJ_CASE_INSENSITIVE + OBJ_KERNEL_HANDLE, NULL, NULL   
invoke ZwCreateFile, addr hDirectory, SYNCHRONIZE, addr oa, addr iosb, 0, FILE_ATTRIBUTE_NORMAL, \
   0, FILE_OPEN_IF, FILE_DIRECTORY_FILE + FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0
.if eax == STATUS_SUCCESS
;------------------------------------------------------------
;文件创建属性
;------------------------------------------------------------
.if iosb.Information == FILE_CREATED
  invoke DbgPrint, $CTA0("目录创建")
;------------------------------------------------------------
;文件共享属性   
;------------------------------------------------------------
.elseif iosb.Information == FILE_OPENED
  invoke DbgPrint, $CTA0("目录共享")
.endif
invoke ZwClose, hDirectory
.else
;------------------------------------------------------------
;格式化输出,创建目录失败!
;------------------------------------------------------------
invoke DbgPrint, $CTA0("无法创建目录,错误代码 %08X"), eax
.endif
ret
CreateDirectory endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;
;打开创建一个文件
;
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
CreateFile proc
local oa:OBJECT_ATTRIBUTES
local iosb:IO_STATUS_BLOCK
local hFile:HANDLE
;-----------------------------------------------------------
;
;格式化输出创建的文件名。在内核中使用Unicode
;Buffer缓冲区保存着文件路径
;
;-----------------------------------------------------------
invoke DbgPrint, $CTA0("创建文件 %ws "), g_usFileName.Buffer
;-----------------------------------------------------------
  ;初始化OBJ_CASE_INSENSITIVE结构
  ;-----------------------------------------------------------
InitializeObjectAttributes addr oa, addr g_usFileName, \
   OBJ_CASE_INSENSITIVE + OBJ_KERNEL_HANDLE, NULL, NULL
;-----------------------------------------------------------   
  ;打开文件
  ;-----------------------------------------------------------
invoke ZwCreateFile, addr hFile, SYNCHRONIZE, addr oa, addr iosb, 0, FILE_ATTRIBUTE_NORMAL, \
   0, FILE_CREATE, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0
.if eax == STATUS_SUCCESS
invoke DbgPrint, $CTA0("文件创建成功")
invoke ZwClose, hFile
.else
invoke DbgPrint, $CTA0("文件创建失败,错误代码: %08X"), eax
.endif
ret
CreateFile endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;
;开始把内容写入这个文件当中   
;
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
WriteFile proc
local oa:OBJECT_ATTRIBUTES
local iosb:IO_STATUS_BLOCK
local hFile:HANDLE
  ;相当于C中的printf
invoke DbgPrint, $CTA0("打开文件准备写入数据")

InitializeObjectAttributes addr oa, addr g_usFileName, \
   OBJ_CASE_INSENSITIVE + OBJ_KERNEL_HANDLE, NULL, NULL
;-----------------------------------------------------------
;
; ZwCreateFile 用来打开文件,所以属性必须指定.
; 如果要对文件进行写操作,可以指定FILE_WRITE_DATA权限,这个和ring3一样
;
;-----------------------------------------------------------
invoke ZwCreateFile, addr hFile, FILE_WRITE_DATA + SYNCHRONIZE, addr oa, addr iosb, \
   0, 0, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0
.if eax == STATUS_SUCCESS
invoke DbgPrint, $CTA0("文件打开成功")
;-----------------------------------------------------------
;
   ;这里是文件内容,使用了CTA0 宏,也可以在.const段来定义
   ;CTA0 "Data can be written to an open file", g_szData,4
   ;使用何种定义,都是个人偏好。下面代码就没什么好注释的了
   ;
   ;-----------------------------------------------------------
   
   CTA0 "看KmdKit爽爽中,其内附一代码,其内容过于复杂,删几段修改测试之,成功,乃大喜,记之.",g_szData,4
invoke ZwWriteFile, hFile, 0, NULL, NULL, addr iosb, \
   addr g_szData, sizeof g_szData - 1, NULL, NULL
.if eax == STATUS_SUCCESS
  invoke DbgPrint, $CTA0("文件写入成功")
.else
  invoke DbgPrint, $CTA0("无法写入文件,错误代码: %08X"), eax
.endif

invoke ZwClose, hFile
.else
invoke DbgPrint, $CTA0("无法打开文件,错误代码: %08X"), eax
.endif

ret

WriteFile endp                     
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;
;驱动程序入口处
;
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING

invoke DbgPrint, $CTA0("驱动入口")
;---------------------------------------------------------------------
;调用函数创建一个目录.刚测试了一下,要创建一个文件,必须先创建其目录.
;这个ZwCreateFile不像ring3的一样,必须要创建文件的目录后,才能创建文件.
;---------------------------------------------------------------------
invoke CreateDirectory
invoke CreateFile   ;创建一个文件
invoke WriteFile    ;把内容写到此文件中

invoke DbgPrint, $CTA0("执行完退出")
mov eax, STATUS_DEVICE_CONFIGURATION_ERROR ;获取失败消息返回
ret
DriverEntry endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end DriverEntry
很简单的一个驱动程序。关于文件操作的。俺喜欢用IDA对程序进行白箱测试,有牛人说,学汇编最好的方法就是反汇编别人的程序。这句话俺深有体会。逆向技术在商业领域用途更广,并且逆向技术已经合法话,玩这个的更有发挥的空间。俺曾经听过一句铞言:给我一个可执行文件,我可以还你一份源码。可见威力。可惜俺的逆向功底不深,对驱动的逆向难免存在遗漏,请大大们指出,俺一定会改正。

  当然,要对驱动的结构有很深的了解才能够分析。但是有些程序是exe的,但是却使用ntdll.dll里的函数,比如系统进程 lsass.exe。这里我简陋分析一下:
复制内容到剪贴板
代码:
.text:010014EC         push  esi       ; 保存寄存器值
.text:010014ED         push  esi      
.text:010014EE         push  1        ;千万别把1当作一个参数。
.text:010014F0         call  loc_10013EF   ; 调用子函数

---------------------------------------------------------------------------
;看到这里就应该明白,这个子函数并没有任何参数传递。所以我也不明白 push 1 是什么意思
loc_10013EF:


.text:010013EF loc_10013EF:            
.text:010013EF         mov   edi, edi
.text:010013F1         push  ebp
.text:010013F2         mov   ebp, esp
.text:010013F4         push  ecx
.text:010013F5         push  esi       ; 上面这些操作都是保存寄存器的值,而非参数。即pushad
.text:010013F6         push  1        ; SEM_NOGPFAULTERRORBOX
.text:010013F8         call  ds:SetErrorMode ; 设置错误代码,如果程序出现异常,不提供任何提示
.text:010013FE         push  offset loc_10011DD
.text:01001403         call  ds:SetUnhandledExceptionFilter ; 程序错误则取其错误地址.这是一个回调函数
.text:01001409         push  4
.text:0100140B         lea   eax, [ebp-4]
.text:0100140E         push  eax
.text:0100140F         push  5
.text:01001411         push  0FFFFFFFFh
.text:01001413         mov   dword ptr [ebp-4], 9
.text:0100141A         call  ds:NtSetInformationProcess ; 把与调度优先级有关的信息设置到目标进程对象中去。具体是什么,我也不清楚
.text:01001420         mov   esi, eax    ; 保存函数返回值到esi
.text:01001422         test  esi, esi    ; 为0否?
.text:01001424         jl   short loc_1001486 ; 这里的esi是NtSetInformationProcess函数的返回值。通过堆栈直接传给这个子函数

------------------------------------------------------------------------------------

loc_1001486:


.text:01001486 loc_1001486:              
.text:01001486                     
.text:01001486                    
.text:01001486                  
.text:01001486                    
.text:01001486                    
.text:01001486         push  esi       ; 这里的esi是NtSetInformationProcess函数的返回值。通过堆栈直接传给这个子函数
.text:01001487         call  sub_10011EE
.text:01001487
.text:0100148C         push  esi
.text:0100148D         call  ds:ExitThread


----------------------------------------------------------------------------------

sub_10011EE:



.text:010011EE sub_10011EE   proc near      
.text:010011EE
.text:010011EE var_48     = dword ptr -48h
.text:010011EE var_44     = dword ptr -44h
.text:010011EE var_40     = dword ptr -40h
.text:010011EE var_38     = dword ptr -38h
.text:010011EE var_34     = dword ptr -34h
.text:010011EE var_30     = dword ptr -30h
.text:010011EE var_2C     = dword ptr -2Ch
.text:010011EE var_28     = dword ptr -28h
.text:010011EE var_24     = dword ptr -24h
.text:010011EE var_20     = dword ptr -20h
.text:010011EE hObject     = dword ptr -1Ch
.text:010011EE pSid      = dword ptr -18h
.text:010011EE var_14     = dword ptr -14h
.text:010011EE var_10     = dword ptr -10h
.text:010011EE pIdentifierAuthority= _SID_IDENTIFIER_AUTHORITY ptr -0Ch
.text:010011EE var_4      = dword ptr -4
.text:010011EE arg_0      = dword ptr 8 ;传递过来的NtSetInformationProcess函数句柄
.text:010011EE
.text:010011EE         mov   edi, edi
.text:010011F0         push  ebp
.text:010011F1         mov   ebp, esp
.text:010011F3         sub   esp, 48h
.text:010011F6         mov   eax, dword_1003004
.text:010011FB         push  ebx
.text:010011FC         push  esi
.text:010011FD         mov   esi, [ebp+arg_0]
.text:01001200         xor   ebx, ebx
.text:01001202         cmp   esi, ebx
.text:01001204         mov   [ebp+var_4], eax
.text:01001207         push  edi
.text:01001208         mov   [ebp+var_10], ebx
.text:0100120B         jl   loc_1001298
.text:0100120B
.text:01001211         push  offset s_Sam_service_s ; "\\SAM_SERVICE_STARTED"
.text:01001216         lea   eax, [ebp+var_40] ; 由此可见,var_40 是一个局部缓冲区变量
.text:01001219         push  eax
.text:0100121A         call  ds:RtlInitUnicodeString
.text:01001220         push  ebx
.text:01001221         lea   eax, [ebp+var_40]
.text:01001224         mov   [ebp+var_2C], eax
.text:01001227         push  ebx
.text:01001228         lea   eax, [ebp+var_34]
.text:0100122B         push  eax
.text:0100122C         mov   esi, 100002h
.text:01001231         push  esi
.text:01001232         lea   eax, [ebp+var_10]
.text:01001235         push  eax
.text:01001236         mov   [ebp+var_34], 18h
.text:0100123D         mov   [ebp+var_30], ebx
.text:01001240         mov   [ebp+var_28], ebx
.text:01001243         mov   [ebp+var_24], ebx
.text:01001246         mov   [ebp+var_20], ebx
.text:01001249         call  ds:NtCreateEvent ; 创建互拆对象,内核中代表着事件对象的数据结构是KEVENT
.text:0100124F         cmp   eax, ebx    ; eax >= ebx ?
.text:01001251         jge   short loc_1001278 ; 如果是,就跳
.text:01001251
.text:01001253         cmp   eax, 40000000h ; eax == 40000000h ?
.text:01001258         jz   short loc_1001261
.text:01001258
.text:0100125A         cmp   eax, 0C0000035h ; eax != 0C0000035h ?
.text:0100125F         jnz   short loc_1001270
.text:0100125F
.text:01001261
.text:01001261 loc_1001261:            
.text:01001261         lea   eax, [ebp+var_34]
.text:01001264         push  eax
.text:01001265         push  esi
.text:01001266         lea   eax, [ebp+var_10]
.text:01001269         push  eax
.text:0100126A         call  ds:NtOpenEvent ; 打开一个内核对象
.text:0100126A
.text:01001270
.text:01001270 loc_1001270:              
.text:01001270         cmp   eax, ebx
.text:01001272         jl   loc_10013DB
.text:01001272
.text:01001278
.text:01001278 loc_1001278:              
.text:01001278         push  ebx
.text:01001279         push  [ebp+var_10]
.text:0100127C         call  ds:NtSetEvent  ; 设置内核对象
.text:01001282         test  eax, eax
.text:01001284         jge   loc_10013DB
.text:01001284
.text:0100128A         push  [ebp+var_10]
.text:0100128D         call  ds:NtClose   ; 关闭
.text:01001293         jmp   loc_10013DB
.text:01001293
.text:01001298 ; ---------------------------------------------------------------------------
.text:01001298
.text:01001298 loc_1001298:              
.text:01001298         push  2        ; ImpersonationLevel
.text:0100129A         call  ds:ImpersonateSelf
.text:010012A0         xor   edi, edi
.text:010012A2         inc   edi
.text:010012A3         test  eax, eax
.text:010012A5         jz   loc_100133F
.text:010012A5
.text:010012AB         lea   eax, [ebp+hObject]
.text:010012AE         push  eax       ; TokenHandle
.text:010012AF         push  edi       ; OpenAsSelf
.text:010012B0         push  8        ; DesiredAccess
.text:010012B2         call  ds:GetCurrentThread ; 获取自身进程PID
.text:010012B8         push  eax       ; ThreadHandle
.text:010012B9         call  ds:OpenThreadToken ; Open the access token associated with a thread
.text:010012BF         test  eax, eax
.text:010012C1         jz   short loc_1001339
.text:010012C1
.text:010012C3         lea   eax, [ebp+pSid]
.text:010012C6         push  eax       ; pSid
.text:010012C7         push  ebx       ; nSubAuthority7
.text:010012C8         push  ebx       ; nSubAuthority6
.text:010012C9         push  ebx       ; nSubAuthority5
.text:010012CA         push  ebx       ; nSubAuthority4
.text:010012CB         push  ebx       ; nSubAuthority3
.text:010012CC         push  ebx       ; nSubAuthority2
.text:010012CD         push  ebx       ; nSubAuthority1
.text:010012CE         push  12h       ; nSubAuthority0
.text:010012D0         push  edi       ; nSubAuthorityCount
.text:010012D1         lea   eax, [ebp+pIdentifierAuthority]
.text:010012D4         push  eax       ; pIdentifierAuthority
.text:010012D5         mov   [ebp+var_14], edi
.text:010012D8         mov   [ebp+pSid], ebx
.text:010012DB         mov   [ebp+pIdentifierAuthority.Value], bl
.text:010012DE         mov   [ebp+pIdentifierAuthority.Value+1], bl
.text:010012E1         mov   [ebp+pIdentifierAuthority.Value+2], bl
.text:010012E4         mov   [ebp+pIdentifierAuthority.Value+3], bl
.text:010012E7         mov   [ebp+pIdentifierAuthority.Value+4], bl
.text:010012EA         mov   [ebp+pIdentifierAuthority.Value+5], 5
.text:010012EE         call  ds:AllocateAndInitializeSid ; Allocate and initializes a security
.text:010012EE                     ; identifier with up to eight subauthorities
.text:010012F4         test  eax, eax
.text:010012F6         jz   short loc_100131F
.text:010012F6
.text:010012F8         lea   eax, [ebp+var_38]
.text:010012FB         push  eax
.text:010012FC         push  [ebp+pSid]
.text:010012FF         push  [ebp+hObject]
.text:01001302         call  CheckTokenMembership
.text:01001302
.text:01001307         test  eax, eax
.text:01001309         jz   short loc_1001311
.text:01001309
.text:0100130B         mov   eax, [ebp+var_38]
.text:0100130E         mov   [ebp+var_14], eax
.text:0100130E
.text:01001311
.text:01001311 loc_1001311:            
.text:01001311         cmp   [ebp+pSid], ebx
.text:01001314         jz   short loc_100131F
.text:01001314
.text:01001316         push  [ebp+pSid]   ; pSid
.text:01001319         call  ds:FreeSid
.text:01001319
.text:0100131F
.text:0100131F loc_100131F:              
.text:0100131F                    
.text:0100131F         push  [ebp+hObject]  ; hObject
.text:01001322         call  ds:CloseHandle
.text:01001328         call  ds:RevertToSelf ; Terminate the impersonation
.text:01001328                     ; of a client application
.text:0100132E         cmp   [ebp+var_14], ebx
.text:01001331         jz   loc_10013DB
.text:01001331
.text:01001337         jmp   short loc_100133F
.text:01001337
.text:01001339 ; ---------------------------------------------------------------------------
.text:01001339
.text:01001339 loc_1001339:              
.text:01001339         call  ds:RevertToSelf ; Terminate the impersonation
.text:01001339                     ; of a client application
.text:01001339
.text:0100133F
.text:0100133F loc_100133F:              
.text:0100133F                     
.text:0100133F         lea   eax, [ebp+var_48]
.text:01001342         push  eax
.text:01001343         push  edi
.text:01001344         lea   eax, [ebp+var_44]
.text:01001347         push  eax
.text:01001348         push  ebx
.text:01001349         push  edi
.text:0100134A         or   esi, 10000000h
.text:01001350         push  esi
.text:01001351         mov   [ebp+var_44], 10010h
.text:01001358         call  ds:NtRaiseHardError
.text:0100135E         mov   esi, eax
.text:01001360         call  LsaISetupWasRun
.text:01001360
.text:01001365         test  al, al
.text:01001367         jz   short loc_10013B4 ; 关闭计算机
.text:01001367
.text:01001369         push  offset s_Setup_failed ; "\\SETUP_FAILED"
.text:0100136E         lea   eax, [ebp+var_40]
.text:01001371         push  eax
.text:01001372         call  ds:RtlInitUnicodeString
.text:01001378         lea   eax, [ebp+var_40]
.text:0100137B         mov   [ebp+var_2C], eax
.text:0100137E         lea   eax, [ebp+var_34]
.text:01001381         push  eax
.text:01001382         push  100002h
.text:01001387         lea   eax, [ebp+var_10]
.text:0100138A         push  eax
.text:0100138B         mov   [ebp+var_34], 18h
.text:01001392         mov   [ebp+var_30], ebx
.text:01001395         mov   [ebp+var_28], ebx
.text:01001398         mov   [ebp+var_24], ebx
.text:0100139B         mov   [ebp+var_20], ebx
.text:0100139E         call  ds:NtOpenEvent
.text:010013A4         test  eax, eax
.text:010013A6         jl   short loc_10013DB
.text:010013A6
.text:010013A8         push  ebx
.text:010013A9         push  [ebp+var_10]
.text:010013AC         call  ds:NtSetEvent
.text:010013B2         jmp   short loc_10013DB
.text:010013B2
.text:010013B4 ; ---------------------------------------------------------------------------
.text:010013B4
.text:010013B4 loc_10013B4:              
.text:010013B4         cmp   esi, ebx
.text:010013B6         jl   short loc_10013DB
.text:010013B6
.text:010013B8         mov   esi, ds:RtlAdjustPrivilege
.text:010013BE         lea   eax, [ebp+var_14]
.text:010013C1         push  eax
.text:010013C2         push  ebx
.text:010013C3         push  edi
.text:010013C4         push  13h
.text:010013C6         call  esi ; RtlAdjustPrivilege
.text:010013C8         push  edi       ; edi == 2 ?
.text:010013C9         call  ds:NtShutdownSystem
.text:010013CF         lea   eax, [ebp+var_14]
.text:010013D2         push  eax
.text:010013D3         push  ebx
.text:010013D4         push  [ebp+var_14]
.text:010013D7         push  13h
.text:010013D9         call  esi ; RtlAdjustPrivilege
.text:010013D9
.text:010013DB
.text:010013DB loc_10013DB:              
.text:010013DB                     
.text:010013DB                    
.text:010013DB                     
.text:010013DB                     
.text:010013DB                    
.text:010013DB         mov   ecx, [ebp+var_4]
.text:010013DE         pop   edi
.text:010013DF         pop   esi
.text:010013E0         pop   ebx
.text:010013E1         call  sub_10015C5
.text:010013E1
.text:010013E6         leave
.text:010013E7         retn  4
.text:010013E7
.text:010013E7 sub_10011EE   endp
下面是lsass.exe的部分代码。俺写得不伦不类。哎,继续加强俺的汇编功底。代码:
复制内容到剪贴板
代码:
;--------------------------------------------------------
;
;code By Asm QQ:448761813
;
;---------------------------------------------------------
.386
.model flat, stdcall
option casemap:none

;--------------------------------------------------------
;
;未编写完成的lsass.exe的代码,就算写完,估计还需要大面积调式
;所以这里不好把头文件和库写出。不过我们总算了解一点东西,
;就是为什么结束了lsass.exe,系统会关机。原来是调用NtRaiseHardError
;来检查错误,发现了,就调用NtShutdownSystem。
;
;----------------------------------------------------------

.data
dword_1003004 dd 0BB40h
.const
CCOUNTED_UNICODE_STRING  "\\SAM_SERVICE_STARTED",g_usSam, 4
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Lsasses proc lpRet:LPSTR
local hEvent1:HANDLE
local hEvent:HANDLE
local szTYPE:EVENT_TYPE
local Message[1024]:DWORD
local Error:HARDERROR_RESPONSE_OPTION
local Response:HARDERROR_RESPONSE
local en:DWORD

mov esi,lpRet
xor ebx,ebx
cmp esi,ebx
mov hEvent1,eax
push edi ;edi是什么,还未知
mov ebx,hEvent
jl   loc_1001298

invoke RtlInitUnicodeString,addr lpBuff,addr g_usSam
invoke NtCreateEvent,hEvent,100002h,CTXT("LsassEvent"),szTYPE.SynchronizationEvent,sizeof szTYPE.SynchronizationEvent;这个函数的写得有点牵强
.if eax>=ebx ;ebx到底是什么?有待进一步分析!
invoke NTSetEvent,hEvent,ebx
.elseif eax==40000000h
invoke NtOpenEvent,hEvent,100002h,CTXT("LsassEvent")
.elseif eax
invoke NtClose,hEvent
.endif

loc_1001298:
      invoke ImpersonateSelf,2
      xor edi,edi
      inc edi
      .if eax==NULL
      jmp loc_100133F
      .endif
      
loc_100133F:
      or esi, 10000000h
      invoke NtRaiseHardError,esi,edi,ebx,addr Message,addr Error,addr Response
      mov esi,eax ;esi是在堆栈中,这里典型的通过寄存器传递参数
      call LsaISetupWasRun
      test al,al
      jz NtShutdown
      
NtShutdown:
     invoke RtlAdjustPrivilege,SE_SHUTDOWN_PRIVILEGE,2,2,addr en
     invoke NtShutdownSystem,2
     invoke RtlAdjustPrivilege,SE_SHUTDOWN_PRIVILEGE,addr en,2,addr en
ret
Lsasses endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
loc_10013EF proc
local Handel:HANDLE
local dwRet:DWORD
invoke SetErrorMode,SEM_FAILCRITICALERRORS
invoke SetUnhandledExceptionFilter,EXCEPTION_ACCESS_VIOLATION
invoke NtSetInformationProcess,0FFFFFFFFh,5,addr Handel,4
.if eax<NULL
mov dwRet,eax
jmp loc_1001486
.endif

loc_1001486:
      invoke Lsasses,dwRet ;执行完这个函数,还不知道到底是做了什么的。
      invoke ExitThread,0
loc_10013EF endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING
invoke loc_10013EF;调用第一个子函数,姑且这么写
mov eax,STATUS_DEVICE_CONFIGURATION_ERROR
ret
DriverEntry endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end DriverEntry

附件

test.sys.rar (2 KB)

2007-4-20 14:28, 下载次数: 49

游戏吧  http://www.game8.cc/MyBlog    http://www.asm32.cn

TOP

支持!本人最近也在努力学汇编。以后要多多向前辈学习!呵呵~~

TOP

还是ASM2C好~~~
http://www.rootkitcn.com

TOP

发新话题