跳转到主内容
极星编程网:以代码为星,赴技术山海!

WinFlash AwdFlash分析

Winflash/AwdFlash是Windows下和dos下的BIOS刷新工具。

在windows下,刷新BIOS需要读写物理内存或IO端口。

在NT平台下,读写物理内存或IO端口需要驱动来支持(也可以使用/dev/PhysicalMemory来完成,但是2003sp1...)winflash使用驱动来实现物理内存/IO端口的读写,这一点很明显。

winflash/awdflash都是使用SMI Flash来进行BIOS刷新的。

对winflash/awdflash反汇编,都可以发现mov     dx, ds:SMI_PORTmov     al, 28hout     dx, al          ; manufacture's diagnostic checkpoint之类的字样.(开始还以为这是调试用的端口.../感谢网友 的文章。

) 废话就不说了,先看一下WinFlash的FlowChart吧: 直接将winflash拖到IDA中也可以,如果你能看得下去... winflash是经过加壳的,用PE Scan检测一下,aspack 2.12可直接脱壳,没有什么特殊的障碍... 在NT下,Winflash需要动态加载驱动,直接在代码中查找CreateService(),然后在逐级找到calller,hehe,最后来到如下位置 snyped:004029A0 084                 mov     ecx, esisnyped:004029A2 084                 call    check_OS_Versionsnyped:004029A2snyped:004029A7 084                 mov     ecx, esisnyped:004029A9 084                 call    Start_SYS_Driversnyped:004029A9snyped:004029AE 084                 test    al, alsnyped:004029B0 084                 jnz     short Check_Award_BIOSsnyped:004029B0snyped:004029B2 084                 lea     ecx, [ebp+var_74]snyped:004029B5 084                 mov     [ebp+var_4], 0FFFFFFFFhsnyped:004029BC 084                 call    CCommandLineInfo::~CCommandLineInfo(void) 有关MFC的东西不用管了,接着看下面主要是调用驱动的功能来读取物理内存的F000:0000段的内容,即SystemBIOS模块的内容(初始化后),从中获取BIOS/FlashROM的相关信息。

snyped:004029D4     Check_Award_BIOS:                       ; CODE XREF: CMainFrame_InitInstance+120jsnyped:004029D4 084                 mov     ecx, offset flash_info_structsnyped:004029D9 084                 call    PhysicalMemoryRead      ;这里使用DeviceIoCtrl的222000h功能;读取0xF0000-0xFFFFF的内存到用户态缓冲区snyped:004029D9snyped:004029DE 084                 mov     ecx, offset flash_info_structsnyped:004029E3 084                 call    Get_Award_Modular_Sig   ;此函数从读取的0xF000段数据中获取BIOS信息;snyped:004029E3snyped:004029E8 084                 test    al, alsnyped:004029EA 084                 jnz     short BIOS_is_Awardsnyped:004029EAsnyped:004029EC 084                 push    offset s_XBiosAwardGb ; " 本机主板 BIOS 不是 Award 的!

"snyped:004029F1 088                 push    1               ; intsnyped:004029F3 08C                 push    0               ; intsnyped:004029F5 090                 mov     ecx, esisnyped:004029F7 090                 call    ErrorDialog__1snyped:004029F7snyped:004029FC 084                 lea     ecx, [ebp+var_74]snyped:004029FF 084                 mov     [ebp+var_4], 0FFFFFFFFhsnyped:00402A06 084                 call    CCommandLineInfo::~CCommandLineInfo(void) 在上面的代码中,最重要的函数就是0x004029E3 位置调用的函数snyped:004011D0     Get_Award_Modular_Sig proc near         ; CODE XREF: CMainFrame_InitInstance+153psnyped:004011D0                                             ; sub_4033A0+8psnyped:004011D0 000                 push    esisnyped:004011D1 004                 mov     esi, ecxsnyped:004011D3 004                 mov     ds:byte_44FB08, 0snyped:004011DA 004                 mov     eax, [esi+4]snyped:004011DD 004                 push    eaxsnyped:004011DE 008                 call    check_Award_Modular_BIOS_Sig    ;当找到"Award Modular BIOS"字符串时,此函数返回1snyped:004011DEsnyped:004011E3 004                 test    al, alsnyped:004011E5 004                 jnz     short loc_4011E9    ;AwdBIOS,在这里跳转snyped:004011E5snyped:004011E7 004                 pop     esisnyped:004011E8 000                 retnsnyped:004011E8snyped:004011E9     ; ---------------------------------------------------------------------------snyped:004011E9snyped:004011E9     loc_4011E9:                             ; CODE XREF: Get_Award_Modular_Sig+15jsnyped:004011E9 004                 mov     ecx, esisnyped:004011EB 004                 call    GetSMI_Port     ;在Offset_" $@AWDFLASH"+0x2A 位置获取SMI_PORTsnyped:004011EBsnyped:004011F0 004                 mov     ecx, esi等snyped:004011F2 004                 call    GetFlashInfo    ;由"KAFLASH" 获取BIOS FlashROM信息,包括FlashROM 大小,Base Addrsnyped:004011F2snyped:004011F7 004                 mov     ecx, esisnyped:004011F9 004                 call    GetDecompressInfo   ;暂时这样认为,获取DecompressBlock的起始位置...(?

?

?

?

)snyped:004011F9snyped:004011FE 004                 mov     al, 1snyped:00401200 004                 pop     esisnyped:00401201 000                 retnsnyped:00401201snyped:00401201     Get_Award_Modular_Sig endp 获取了BIOS和FlashROM的相关信息后,下面是设置驱动的全局变量,SMI_PORT其中IoCtlCode:222004h-->设置驱动的全局变量,(in/out Buffer见下面)222008h-->调用SMI_0x2E功能 snyped:00402A1E     BIOS_is_Award:                          ; CODE XREF: CMainFrame_InitInstance+15Ajsnyped:00402A1E 084                 cmp     ds:Window_Version, 2000hsnyped:00402A28 084                 jnz     short SMI_0x2E_Func_0snyped:00402A28snyped:00402A2A 084                 mov     ax, ds:SMI_PORTsnyped:00402A30 084                 lea     ecx, [ebp+BytesReturned]snyped:00402A33 084                 mov     edi, ds:DeviceIoControlsnyped:00402A39 084                 push    0               ; lpOverlappedsnyped:00402A3B 088                 push    ecx             ; lpBytesReturnedsnyped:00402A3C 08C                 push    0               ; nOutBufferSizesnyped:00402A3E 090                 push    0               ; lpOutBuffersnyped:00402A40 094                 lea     edx, [ebp+SMI_Port]snyped:00402A43 094                 mov     word ptr [ebp+SMI_Port], axsnyped:00402A47 094                 mov     eax, ds:hDevicesnyped:00402A4C 094                 push    2               ; nInBufferSizesnyped:00402A4E 098                 push    edx             ; lpInBuffersnyped:00402A4F 09C                 push    222004h ; ; dwIoControlCodesnyped:00402A54 0A0                 push    eax             ; hDevicesnyped:00402A55 0A4                 call    edi ; DeviceIoControl ; Set SMI Port!!!snyped:00402A57 084                 lea     ecx, [ebp+BytesReturned]snyped:00402A5A 084                 push    0               ; lpOverlappedsnyped:00402A5C 088                 push    ecx             ; lpBytesReturnedsnyped:00402A5D 08C                 mov     ecx, ds:hDevicesnyped:00402A63 08C                 lea     edx, [ebp+OutBuffer]snyped:00402A66 08C                 push    10h             ; nOutBufferSizesnyped:00402A68 090                 push    edx             ; lpOutBuffersnyped:00402A69 094                 lea     eax, [ebp+OutBuffer]snyped:00402A6C 094                 push    2               ; nInBufferSizesnyped:00402A6E 098                 push    eax             ; lpInBuffersnyped:00402A6F 09C                 push    222008h ; ; dwIoControlCodesnyped:00402A74 0A0                 push    ecx             ; hDevicesnyped:00402A75 0A4                 mov     [ebp+OutBuffer], 0snyped:00402A7C 0A4                 call    edi ; DeviceIoControl ; SMI_0x2E Func 00hsnyped:00402A7C                                             ; GetBiosInfosnyped:00402A7E 084                 cmp     ds:Window_Version, 2000hsnyped:00402A88 084                 jz      short loc_402AA5 ; jmp here!!!///MFC Init here... 基本上,WinFlash的基本init_FlowChart就出来了下面转到到正题: 至于WinFlash怎样Program FlashROM,只需调试一下winflash.exe即可 说的太麻烦大家有各自的调试手段我使用的是IDA5来进行Ring3调试的(hehe),直接用ida5启动(unpacked)winflash.exe,然后在刷新BIOS时将进程中断,即可由中断的代码位置来判断caller(call tree/path?) 基本上,刷新的代码部分如下,注视自己随便填写了,看得懂即可 ////winflash代码里针对win98和NT做了不同的处理,这里只关心NT//snyped:0040209F     os_is_win2000:                          ; CODE XREF: SST_SectorProg+19jsnyped:0040209F 018                 mov     eax, [esp+18h+BytesReturned]snyped:004020A3 018                 lea     ecx, [esp+18h+BytesReturned]snyped:004020A7 018                 mov     ebx, ds:DeviceIoControlsnyped:004020AD 018                 push    0               ; lpOverlappedsnyped:004020AF 01C                 push    ecx             ; lpBytesReturnedsnyped:004020B0 020                 push    0               ; nOutBufferSizesnyped:004020B2 024                 push    0               ; lpOutBuffersnyped:004020B4 028                 lea     edx, [esp+28h+LocalBuffer] ; input buffer dd FFFC0000hsnyped:004020B4                                             ;snyped:004020B8 028                 mov     [esp+28h+LocalBuffer], eaxsnyped:004020BC 028                 mov     eax, ds:hDevicesnyped:004020C1 028                 push    4               ; nInBufferSizesnyped:004020C3 02C                 push    edx             ; lpInBuffersnyped:004020C4 030                 push    222010h ; ; dwIoControlCodesnyped:004020C9 034                 push    eax             ; hDevicesnyped:004020CA 038                 call    ebx ; DeviceIoControl ; SetGlobal_Varsnyped:004020CC 018                 mov     edi, [esp+18h+Size_0x1000] ; edi==0x1000snyped:004020D0 018                 test    edi, edi        ; EDI=FFFC0000h //很多注释都是调试的时候加上去的,应该很明显的....snyped:004020D2 018                 jbe     short loc_4020FEsnyped:004020D2snyped:004020D4 018                 add     edi, 0Fh        ; edi=0x100Fsnyped:004020D7 018                 shr     edi, 4          ; edi=0x100snyped:004020D7snyped:004020DAsnyped:004020DA     loop_Byte_program:                      ; CODE XREF: SST_SectorProg+ACjsnyped:004020DA 018                 mov     eax, ds:hDevicesnyped:004020DF 018                 lea     ecx, [esp+18h+BytesReturned]snyped:004020E3 018                 push    0               ; lpOverlappedsnyped:004020E5 01C                 push    ecx             ; lpBytesReturnedsnyped:004020E6 020                 lea     edx, [esp+20h+OutBuffer]snyped:004020EA 020                 push    4               ; nOutBufferSizesnyped:004020EC 024                 push    edx             ; lpOutBuffersnyped:004020ED 028                 push    10h             ; nInBufferSizesnyped:004020EF 02C                 push    esi             ; lpInBuffersnyped:004020F0 030                 push    22201Ch ; ; dwIoControlCodesnyped:004020F5 034                 push    eax             ; hDevicesnyped:004020F6 038                 call    ebx ; DeviceIoControl ; 处理16个字节,flash 16Bytessnyped:004020F8 018                 add     esi, 10h        ; 移动到下16个字节snyped:004020FB 018                 dec     edi             ; 总数减去16字节snyped:004020FC 018                 jnz     short loop_Byte_program ; 循环处理snyped:004020FCsnyped:004020FEsnyped:004020FE     loc_4020FE:                             ; CODE XREF: SST_SectorProg+23jsnyped:004020FE                                             ; SST_SectorProg+82jsnyped:004020FE 018                 pop     edisnyped:004020FF 014                 pop     esisnyped:00402100 010                 pop     ebpsnyped:00402101 00C                 mov     al, 1snyped:00402103 00C                 pop     ebxsnyped:00402104 008                 add     esp, 8snyped:00402107 000                 retn    0Chsnyped:00402107snyped:00402107     SST_SectorProg  endp//SST是自己之前随便写的,还以为针对每种Flash有不同的flash方法函数... 在Flash之前,先使用SMI_0x29按4KB擦除ROM... 麻烦 看到这里你可能还是很糊涂,到底怎样Flash?

winflash.exe是请求winflash.sys来完成Flash的,直接静态反汇编winflash.sys即可(文件很简单,是个普通的driver/文件很小...) 至于各个寄存器的设置,反汇编的代码里看得很清楚了。

如果有疑问,可以使用softice调试一下:做法是在winflash刷新的时候,ctrl+d,然后addr winflashmod winflash.sys找到winflash的加载基址然后根据IDA反汇编的代码偏移计算出需要中断的代码位置,然后bpx即可.(也可以直接单步跟踪,如果你很有耐心的话...) 这样,winfash的FlowChart基本上出来了你也可以自己写一个Flash BIOS的程序(前提是awd/SMI Flash...) 不想说废话了这里加一个自己部分注释的winflash.* 的IDB(适用于IDA5)地址.link:   winflash_unpack.idb http://xxx link:   winflash_sys.idb http://xxx //后面提供一个集中下载的位置...

相关文章