- 注册时间
- 2011-8-8
- 最后登录
- 1970-1-1
该用户从未签到
|
又屈服在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
- 这里,我们已经构造出整个程序的结构。即:格式化打印信息-----分别调用三个子函数-------程序返回。这样一来,就可以重组出这个代码的框架:
- Copy code
- .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。
- Copy code
- .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
- Copy code
- .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
- ;
- ;-----------------------------------------------
- .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 '/','?','?','c',':','/','F','i','l','e','W','o','r','k','s','/','t','e','s','t','.','t','x','t',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
- ;
- ;---------------------------------------------------------
- .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
复制代码 |
|