逆向分析并重组源码的过程

Unity3D资源逆向实战:如何用AssetStudio源码定制化破解加密游戏包 本文深入解析Unity3D资源逆向工程,重点介绍如何通过定制AssetStudio源码破解加密游戏包。从Unity资源加密机制到AssetStudio源码架构,再到典型加密方案破解实战,提供了一套完整的逆向工程解决方案,帮助开发者应对复杂的资源加密场景。 阅读详情
 文章作者:asm
信息来源:邪恶八进制信息安全团队

   又屈服在goldberg的淫威下了。麻痹,一提到此人我就性趣勃勃。或许是他给俺力量,刚和他聊完,就怀上了这篇文章,由此可见,goldberg的能力之强。废话少说了,文章开始临盆。

Copy code
.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调用了,所以就不存在任何参数传递。

Copy code
.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

在创建目录后同时测试其属性,分别打印。下面是重组的代码:

Copy 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


  现在来看第二个子函数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。下面是源码:

Copy code
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


    到此,三个未知的子函数已经逐一逆向出源码。程序的流程我们已经很清楚---创建目录----创建文件----写入数据到文件。现在整理一下得出完整代码:

Copy code
;-----------------------------------------------
;
;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 '/','?','?','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。这里我简陋分析一下:

Copy code
.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的部分代码。俺写得不伦不类。哎,继续加强俺的汇编功底。代码:

Copy code
;--------------------------------------------------------
;
;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

逆向分析Codesys V3私有协议:用C#实现PLC变量读写与安全登录(附完整源码) 本文深入解析了Codesys V3私有协议的通信架构与安全机制,通过逆向工程方法详细介绍了协议的四层架构设计,包括块驱动层、数据报层、通道层和服务层。文章还提供了使用C#实现PLC变量读写与安全登录的完整解决方案,包含批量读写优化、安全认证流程及异常处理机制,并附有实用源码示例。 阅读详情

相关推荐

微信小程序逆向解析:wxappUnpacker工具实战与源码分析指南

逆向工程是软件安全领域的重要技术手段,其核心原理是通过分析已编译程序的结构与逻辑,还原其原始设计思路与实现方式。在移动应用生态中,这项技术对于安全审计、漏洞挖掘和竞品分析具有显著价值。微信小程序作为轻量化应用的代表,其代码以加密的.wxapkg包形式分发,这促使了wxappUnpacker等开源逆向工具的出现。该工具基于Node.js开发,通过模拟微信客户端的解密流程,能够将加密包还原为可读的JavaScript、WXML和WXSS源码。在实际应用场景中,开发者可借助此类工具进行代码审计、学习优秀实现方案,

weixin_29327525的博客 890

汇编逆向-入门

JAE;无符号大于等于则跳转JE;等于则跳转JB;无符号小于则跳转JAE;无符号大于等于则跳转JE;等于则跳转JB;无符号小于则跳转。

xinqingwuji的博客 2078

Godzilla加密流量逆向:从AES-ECB到Gzip解压的全过程拆解

本文深入解析Godzilla木马的加密流量逆向过程,从AES-ECB解密到Gzip解压的全套技术方案。通过实战案例演示如何识别流量特征、提取密钥、实现解密算法,并处理动态密钥和分段传输等复杂场景,为网络安全研究人员提供完整的加密流量分析解决方案。

weixin_28607671的博客 637

如何将汇编语言逆向成为C语言

一、应用场景 逆向过程中往往需要将汇编语言逆向成为C语言,IDA是一个很好的工具,给我们逆向工作带来了很大的便利,但是,如果IDA没有识别出来代码呢,jumpOUT,我们需要掌握将汇编语言直接转成C。 二、反汇编技巧(摘取自 天书夜读) 2.1 首先,将流程代码与数据计算的代码分开,我们使用 F: 用于标识 调用函数或者作为函数被调用,出栈、入栈 ...

生命不息 折腾不止 3万+

从抓包失败到源码还原:一次某红书小程序逆向实战复盘

本文详细记录了某红书小程序逆向实战的全过程,从抓包失败到通过WeChatOpenDevTools-Python工具和wxapkg解密技术还原源码。文章分享了逆向工程中的关键技巧,包括定位缓存目录、解密wxapkg文件以及破解加密逻辑,为开发者提供了宝贵的小程序逆向经验。

weixin_28716443的博客 994

Unity IL2CPP逆向实战:Cpp2IL工具原理与逆向分析全解析

在软件逆向工程领域,理解编译后程序的内部逻辑是安全分析、漏洞挖掘和竞品研究的基础。传统.NET程序可通过中间语言(IL)进行反编译分析,但Unity引擎的IL2CPP技术将C#代码编译为C++并进一步优化为原生机器码,导致符号信息和代码结构严重丢失,形成逆向分析的“黑盒”。Cpp2IL作为专门针对IL2CPP的逆向工具,通过解析global-metadata.dat元数据文件和游戏二进制文件,重建出可读的IL代码和类型系统,其核心价值在于突破了IL2CPP的逆向壁垒。该工具在游戏安全审计、外挂原理分析、协议

weixin_34306593的博客 449

逆向学习笔记二

逆向

qq_46804551的博客 693

逆向分析实战:如何把一个未知的dtb文件反编译并验证其正确性?

本文详细介绍了如何逆向分析未知的dtb文件,包括工具链准备、深度反编译技术、验证体系构建以及复杂设备树处理技巧。通过实际案例和进阶命令,帮助开发者掌握从黑盒DTB到可验证DTS的完整方法论,确保硬件描述的准确性和一致性。

weixin_30567225的博客 470

[Python逆向] 逆向Pyinstaller打包的exe文件源码及保护

我们都知道可以使用库可将.py文件编译成.exe文件运行,这篇文章我们就从将脚本编译成.exe并将.exe的源码内容反编译出源文件,再顺便谈谈如何防止被逆向。

杰孑的博客 1万+

Webshell通信协议逆向分析:从抓包到解码中国菜刀流量实战

网络协议分析是网络安全领域的核心基础,它通过解析数据包的格式与内容来理解通信行为。其原理在于对网络流量进行捕获、解码与重组,从而透视应用层交互逻辑。这项技术的核心价值在于能够识别异常通信、检测潜在威胁,广泛应用于入侵检测、恶意软件分析和安全运维等场景。以Webshell通信为例,攻击者常利用加密和编码技术(如Base64、XOR)来隐藏恶意指令,规避传统检测。通过Wireshark抓包和流量分析,可以逐步拆解此类私有协议,提取关键特征。本文聚焦中国菜刀(Chopper)这一典型工具,详细演示如何从原始流量中

weixin_30642869的博客 413

手把手教你用LaTeX完成Elsevier期刊投稿:附完整文件上传清单与注意事项

本文提供了一份详尽的Elsevier期刊LaTeX投稿实战指南。文章系统拆解了从稿件准备、文件上传到最终提交的全流程,重点解析了Manuscript、Figure(s)等关键文件的上传逻辑与注意事项,并附有PDF生成前后的详细检查清单,旨在帮助研究者高效、规范地完成投稿,规避常见错误。

weixin_29300931的博客 490

对简单的EXE文件进行逆向分析

(4)对生成的EXE文件进行反汇编和逆向工程,得到能够在控制台上输出“Reverse Eng”的EXE程序。④直接对ASCII进行修改,将Hllo World修改为Reverse Eng。默认情况下,输出目录为项目文件夹下的“Debug”或“Release”文件夹。(1)使用VC++,C语言编写简单的hello world程序。getchar();②在底部command中输入 d+空格+字符串位置,进行定位。(3)将hello word文件拖到ollydbg中。⑤将字符串结束的HEX数据修改为0。

m0_62821046的博客 7388

LRTimelapse Pro v7.0.0 激活版下载安装教程 (延迟摄影后期渲染)

LRTimelapse Pro 是一款优秀的高级延时摄影解决方案,使用将为用户提供最全面的工具和功能,从导入和组织您的延时摄影序列、视觉工作流程、在 LRTimelapse 中直接编辑和渲染、视觉去闪烁等等,功能齐全,可以使用 LRTimelapse Pro 编辑多个序列时显著提高您的效率,轻松在 LRTimelapse 中配置和使用色彩管理,进行长期延时编辑,在 LRTimelapse Pro 中使用长期工作流程。为延时编辑、关键帧、分级和渲染提供最全面的解决方案。

wyqshusan的博客 3467

Python EXE逆向分析技术:从打包文件到源码还原的专业指南

在Python应用安全分析和恶意软件检测领域,Python打包可执行文件的逆向分析已成为安全研究人员和开发者的必备技能。本文将详细介绍如何使用专业的Python EXE解包工具,对py2exe和pyinstaller打包的程序进行深度逆向分析。 ## 技术挑战:为什么需要专门的解包工具 Python打包工具将Python脚本及其依赖项封装成独立的可执行文件,这种封装过程往往会对原始代码进行压缩

gitblog_00515的博客 711

创龙 瑞芯微 RK3588 国产2.4GHz八核 工业开发板—ISP图像处理开发案例

创龙科技研发的 TL3588-EVM 评估板具备强大视频处理能力,可满足多场景视频开发需求。为助力开发者快速上手,本文整理 7 个实用视频开发案例,涵盖从采集到显示的全流程,详细说明各案例的硬件连接、参数配置与代码解析,帮助开发者高效实现评估板视频相关功能开发与调试。

创龙,嵌入式一体化解决方案商 210

【图像超分】论文精读:Accelerating the Super-Resolution Convolutional Neural Network(FSRCNN)

作为应用于图像超分辨率 (SR) 的成功深度模型,超分辨率卷积神经网络 (SRCNN) [1,2] 在速度和恢复质量方面都比以前的手工制作的模型表现出更好的性能。然而,高计算成本仍然阻碍了它的实际使用,这需要实时性能(24 fps)。在本文中,我们旨在加速当前的 SRCNN,并提出了一种紧凑的沙漏形 CNN 结构,以实现更快和更好的 SR。我们从两个方面重新设计了SRCNN结构。首先,我们在网络末端引入了一个反卷积层,然后将映射直接从原始低分辨率图像(无插值)学习到高分辨率图像。其次,我们通过在映射之前缩小

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 1万+

解密微信小程序逆向解析:WxAppUnpacker实战指南

当你遇到加密的.wxapkg文件时,是否曾好奇里面藏着怎样的代码逻辑?作为开发者,如何在合法合规的前提下,通过技术手段探索小程序的内部构造?本文将以"技术侦探"的视角,带你揭开微信小程序打包文件的逆向解析奥秘。 ## 解密档案:工具初识 ???? **什么是WxAppUnpacker** 一款开源的微信小程序逆向解析工具,能将.wxapkg格式(微信小程序打包格式)的文件还原为可读的源代码和资...

gitblog_00500的博客 1359

LLC变压器,常见的4大问题解决方案

其中之一是当付边的绕组的匝数或层数较多的时候,层间或匝间寄生电容和付边的漏感发生一个寄生的振荡,轻载的时候,这个振铃的幅度会达到很高,导致输出电压比设计的要高许多。但当输入是低压的时候,开关频率比较低,LLC谐振回路的增益较大,因而比较容易发生变压器饱和的问题。由于LLC变压器工作在LC谐振状态,LC谐振回路有个特点就是Q值问题,在这里Q值是大于1的,因而就会有实际加在变压器上的电压要比输入电压高的问题,因而在设计变压器的时候就必须考虑到这一点,否则变压器就不是工作在你设计的磁感应强度上。

1266

Python EXE逆向解密终极指南:从加密打包到源码还原

你是否面对过被PyInstaller加密打包的Python程序束手无策?作为开发者和安全研究员,逆向分析Python EXE文件是必备技能。本文将为你揭示Python字节码反编译的完整流程,助你轻松解密加密程序。 ## 逆向工程核心挑战 **技术壁垒分析:** - PyInstaller的AES加密机制 - 缺失Python magic数的字节码文件 - 版本兼容性问题导致的解析失败 - 复杂

gitblog_00483的博客 1666

华为OD面试八股真题 - 操作系统 - 1

华为OD技术面,操作系统相关八股真题提供详细解答,这篇博客主要涉及于进程和线程相关知识点

qq_45776114的博客 1644

如何利用Dpabi,AFNI,FSL软件计算种子点的功能连接?

fsl_glm 得到的是线性回归系数(beta coefficient),由于在自变量和因变量标准化(均值为 0,标准差为 1)的情况下,简单线性回归的回归系数和皮尔逊相关系数是相同的,因此这是一种间接的方法。(3)上一步得到的 PCC.nii.gz 文件是 Harvard-Oxford 概率模板中的后扣带回,每个体素中的数值(1-100)表示该体素属于 PCC 的概率,反映 PCC 在不同被试中的变异大小,也表示我们对于某个体素属于PCC 的信心。接下来,我们来聊聊功能连接在数据处理里的具体应用。

从事脑科学核磁共振方法学研究,在Nature communications等权威期刊发表研究论文,熟练掌握磁共振处理方法和统计学方法,欢迎大家和我交流。 7842

Python EXE逆向解密终极指南:从打包程序到源码还原完整教程

Python EXE逆向解密是安全研究和软件分析领域的核心技术,而python-exe-unpacker正是这个领域的瑞士军刀。这个开源工具专为逆向分析PyInstaller和py2exe打包的Python可执行文件而设计,帮助开发者、安全研究员和逆向工程师轻松解密加密程序、还原源代码结构。 ## 技术背景与挑战:为什么需要Python EXE逆向工具? 在Python应用分发过程中,PyIn

gitblog_00574的博客 126

【GlobalMapper精品教程】074:从Lidar点云创建3D地形模型

本文基于地形点云数据,基于泊松方法、贪婪三角形测量方法和阿尔法形状创建3d地形模型。

智慧空间实验室 2171

Python EXE逆向解密深度解析:从加密打包到源码还原的完整流程

Python EXE逆向解密是安全研究人员和开发者必备的核心技能,尤其在恶意软件分析、代码审计和软件逆向工程领域具有重要价值。Python EXe-unpacker作为一款专业的**Python EXE解包工具**,提供了完整的**PyInstaller逆向工程**和**字节码反编译**解决方案,能够高效处理加密打包的Python可执行文件,实现源码级别的还原分析。 ## 技术背景与逆向工程挑战

gitblog_00991的博客 117

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

学习逆向需要掌握的基础和工具介绍

** 逆向所需的一些基础及工具 ** Android逆向工程师技能表 密码学基础 • 1.1 古典密码学基础 • 1.2. 代密码学基础 • 1.2.1. 哈希算法 • 1.2.2. 非对称加密与解密 • 1.2.3. 椭圆曲线 • 1.2.4. 数字签名 • 1.2.5. 数据分组与校验 • 1.3. 密码攻击理论 • 1.4. 密码库的识别 网络...

qq_41242968的博客 1854

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

微信小程序逆向分析十大核心技术:从解密到动态调试全解析

逆向工程是软件安全与开发领域的一项关键技术,它通过分析已编译程序来理解其内部工作原理与数据流向。其核心原理在于对二进制或字节码进行反汇编、反编译与动态调试,从而还原出可读的代码逻辑与算法。这项技术的价值不仅在于安全审计与漏洞挖掘,更能帮助开发者深入理解复杂系统的架构设计、排查疑难问题,并学习优秀的工程实践。在移动应用、嵌入式系统及软件保护等场景中,逆向分析都是不可或缺的技能。本文将聚焦于微信小程序这一具体应用场景,深入剖析其包文件(.wxapkg)的定位、解密密钥推导及JavaScript反编译等核心环节,

weixin_26642481的博客 816

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

上一篇: 支持2000和2003下完美进行任意用户克隆
下一篇: 一个汇编版的NDIS驱动程序模板
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值