首页
社区
课程
招聘
[原创]FlashBoot DIY教程
发表于: 2008-3-5 16:53 13960

[原创]FlashBoot DIY教程

2008-3-5 16:53
13960
下有doc,带图
FlashBoot DIY教程

下载页面:  http://www.prime-expert.com/flashboot/
软件大小:  5MB以上
软件简介:  shBoot is a tool to make USB flash disks bootable. It is highly configurable, has many options and was designed to be compatible with all USB disks and BIOSes.
            
【作者声明】:只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教,写教程很累,格式纯属抄袭。
【DIY 目的】:偷懒,启动后直接进入我们需要的功能页,并且调整界面,并且只点一次下一步就自动开始格式化。

【所用工具】:WinXP、OllyDBG、PEiD、LordPE、Vistual Studio 2005
【BTW 一下】:我DIY的是截至到现在官方最新版,由于我是壳盲,所以是某兄给我的脱壳后的文件,如果你也想自己试验,脱壳自想办法。
—————————————————————————————————
【DIY过程】:
首先先看看我们需要做的第一步,自动选择功能页,软件启动后显示欢迎信息,然后点击下一步,然后选择功能,我们的第一个目标就是要省去这个步骤,直接显示我们的选项页。
首先用资源工具一看没有窗体资源,由此怀疑是动态创建,od载入下段CreateWindowExA,W,无果,再下段CreateDialogRedirectA,CreateDialogIndirectParamW 断下来了,观察pTemplate参数,发现不在exe空间内,由此判断是动态创建,稍微跟踪下就发现是类脚本解释的东西,具体是啥,不去追究。
打开窗口记录器



发现很有规律,控件都是作为子窗口创建于一种类名为wxWindowClass的窗口,且所有页窗口均已创建,因此怀疑下一步只是简单的ShowWindow这些宿主窗口,由此下断ShowWindow,这里我不准备google wxWindowClass找他使用的是开发包,因为超出我的理解能力范围了。注意要在程序运行起来后下,不然创建那么多窗体,即使用SW_SHOW过滤也有好几个。下好断点后我们点下一步,果然断下来了:



注意观察堆栈,然后F9,果然是简单的显示英藏宿主窗体,注意,思路非常重要,下一步只有一个,且下一步后句柄尚未变化,说明所有选项页切换都是在这个Button的回调过程中完成的,当然就包括我们现在断下来的代码,因此我们继续往下跟,多用断点测试,调试多次,我们很容易发现:



这个函数既为Botton的Proc,且



函数为关键的代码解释执行函数,我们在这个函数上下段发现程序启动会调用一次来显示初始化页面,而且还有一个更为关键的信息我们很容易的从代码上看出来,那就是这些代码均使用C++完成,意味着我们可以跟踪ECX的值来猜测很多代码工作。现在我们需要仔细分析下代码了,这个过程复杂,自己想办法,我这里直接给出概要
004527EF         55                  push    ebp
004527F0         8BEC                mov     ebp, esp
004527F2         56                  push    esi                                 ; flashboo.0055EC08
004527F3         8BF1                mov     esi, ecx
004527F5         83BE 90010000 00    cmp     dword ptr [esi+190], 0 //判断当前页类指针是否为NULL,我们由此可以得到一个很重要的信息,ESI为一个类,他的ESI+190处存放当前选项页类,也就是wxwindowClass窗体类

004527FC         74 12               je      short 00452810
004527FE         8B8E 90010000       mov     ecx, dword ptr [esi+190]
00452804         8B01                mov     eax, dword ptr [ecx]
00452806         FF90 DC000000       call    dword ptr [eax+DC]
0045280C         84C0                test    al, al
0045280E         74 3A               je      short 0045284A
00452810         8B45 08             mov     eax, dword ptr [ebp+8]
00452813         E8 439FFFFF         call    0044C75B
00452818         3B86 A4010000       cmp     eax, dword ptr [esi+1A4]
0045281E         8B8E 90010000       mov     ecx, dword ptr [esi+190]
00452824         8B01                mov     eax, dword ptr [ecx]
00452826         0F9445 08           sete    byte ptr [ebp+8]
0045282A         807D 08 00          cmp     byte ptr [ebp+8], 0
0045282E         74 08               je      short 00452838
00452830         FF90 14020000       call    dword ptr [eax+214]//查找选项页类指针
00452836         EB 06               jmp     short 0045283E
00452838         FF90 10020000       call    dword ptr [eax+210]// 查找选项页类指针
0045283E         FF75 08             push    dword ptr [ebp+8]
00452841         8BC8                mov     ecx, eax
00452843         8BD6                mov     edx, esi                            ; flashboo.0055EC08
00452845         E8 D0FAFFFF         call    0045231A        //解释执行核心代码,成功返回1,其他为0
0045284A         5E                  pop     esi                                 ; 0012F350
0045284B         5D                  pop     ebp                                 ; 0012F350
0045284C         C2 0400             retn    4
好了,现在我们直接下一步到我们需要的页上,再下断点,点击下一步可以跟入00452830或者00452838查看如何获取下一页选项页指针,经过跟踪我们发现,指针也是定义于ESI指向的类中,同样我们下段刚才提到的45231A,在启动时断下来反流程到
0040A49C         56                  push    esi
0040A49D         8DB7 F8010000       lea     esi, dword ptr [edi+1F8]
0040A4A3         E8 27010300         call    0043A5CF
0040A4A8         FFB7 AC010000       push    dword ptr [edi+1AC] //这里取出其实页类指针,我们只需要patch为我们需要的页,我DIY的是需要到+1C0,这个是从上面提到的00452830或者00452838跟出来的便宜,因此直接patch为push [edi+1C0], 第一个目标完成。

下一步目标:点击下一步后自动完成功能,这个有几种方法,我选择的是模拟鼠标事件,因此代码量很大,所以我们当然不能直接asm,那样要死人的,拿出我们的vs2005吧,
#pragma comment(linker,"/BASE:0x920000")
#pragma comment(linker,"/merge:.rdata=.data")
#pragma comment(linker,"/merge:.data=.text")
#pragma comment(linker,"/ALIGN:0x200")
#pragma comment(linker,"/ENTRY:Entry")
并且编译属性的清单嵌入不要选,也不生成重定位,这样编译出来的代码就只有一个区段,我们直接补到exe后面,既然上面我们分析了下一步的执行过程,那么我们可以在
call    0045231A//解释执行代码
后接管代码,于是我们有了入口
void __declspec(naked) Entry()
{
        __asm
        {
                push        eax
                push        ecx
                mov                ecx,[esp+0x18]//取出传递过来的类,也就是主类
                mov                eax,[ecx+0x190]//取出当前窗体类指针,这里要注意,当0045231A执行成功后,当前窗体会被设置为下一页,我们由此判断是否执行成功
                cmp                eax,[ecx+0x1DC]//下一页的偏移,在上面提到获取方法
                pop                ecx
                pop                eax
                jnz                lab_Normal
                pushad
                mov                eax,0x4DC3D4//GetProcAddress的导入表填充地址
                push        [eax]//取出立即地址,
                call        InitOnce//初始化我们需要使用到的函数
                call        AutoIt//进入模拟事件函数
                popad
lab_Normal:
                pop     esi
                pop     ebp
                retn    4
        }
}

这样自动完成和自动选择选项功能就有了。
下面我们来调整界面,在上面我们发现
00452716         6A 01               push    1
00452718         8BD6                mov     edx, esi
0045271A         E8 FBFBFFFF         call    0045231A//这里进入我们说的解释执行核心,创建窗体就在这里
0045271F         8B06                mov     eax, dword ptr [esi]
00452721         8BCE                mov     ecx, esi
00452723         FF90 3C020000       call    dword ptr [eax+23C]//这里既进入消息循环了,由此45271F成了我们patch的最佳地点
00452729         2D EC130000         sub     eax, 13EC
0045272E         F7D8                neg     eax
00452730         1BC0                sbb     eax, eax
00452732         40                  inc     eax
00452733         5E                  pop     esi                                 ; kernel32.7C816FD7
00452734         C2 0400             retn    4

同样入口
void __declspec(naked) InitWindow()
{
        __asm
        {
                pushad
                mov                eax,0x4DC3D4
                push        [eax]
                call        InitOnce
                call        FixWindowPos//执行Fix核心,
                popad
                mov     eax, dword ptr [esi]
                mov     ecx, esi
                call    dword ptr [eax+0x23C]
                push        0x452729
                ret

        }
}

DIY不难,难度在于调整控制代码上,最好一次多写代码,因为调试麻烦。
编译出DLL后,

转存数据,

注意,我们需要添加一个空区段,大小为0x1000冒充PE头,然后再把真实的区段补上去,然后修改patch点,分别跳转到接管函数入口,



到此我们的DIY完工,运行效果如下

,下面给出代码,

#pragma comment(linker,"/BASE:0x920000")
#pragma comment(linker,"/merge:.rdata=.data")
#pragma comment(linker,"/merge:.data=.text")
//#pragma comment(linker,"/ALIGN:0x200")
#pragma comment(linker,"/ENTRY:Entry")
//#include <wtypes.h>
#include <windows.h>
typedef FARPROC (WINAPI* PENTRY_GetProcAddress)( __in HMODULE hModule, __in LPCSTR lpProcName );
typedef HWND (WINAPI* PENTRY_FindWindowExA)(__in_opt HWND hWndParent, __in_opt HWND hWndChildAfter, __in_opt LPCSTR lpszClass, __in_opt LPCSTR lpszWindow);
typedef HMODULE (WINAPI* PENTRY_GetModuleHandleA)( __in_opt LPCSTR lpModuleName );
typedef DWORD (WINAPI* PENTRY_GetWindowThreadProcessId)(__in HWND hWnd, __out_opt LPDWORD lpdwProcessId);
typedef DWORD (WINAPI* PENTRY_GetCurrentProcessId)();
typedef int (WINAPI* PENTRY_GetWindowTextA)( __in HWND hWnd, __out_ecount(nMaxCount) LPSTR lpString, __in int nMaxCount);
typedef BOOL (WINAPI* PENTRY_PostMessageA)(__in_opt HWND hWnd, __in UINT Msg, __in WPARAM wParam, __in LPARAM lParam);
typedef BOOL (WINAPI* PENTRY_SendMessageA)(__in_opt HWND hWnd, __in UINT Msg, __in WPARAM wParam, __in LPARAM lParam);
typedef BOOL (WINAPI* PENTRY_GetWindowRect)(__in HWND hWnd, __out LPRECT lpRect);
typedef int (WINAPI* PENTRY_GetClassNameA)( HWND hWnd, LPTSTR lpClassName, int nMaxCount );
typedef BOOL (WINAPI* PENTRY_ShowWindow)(__in HWND hWnd, __in int nCmdShow);
typedef BOOL (WINAPI* PENTRY_MoveWindow)(__in HWND hWnd, __in int X, __in int Y, __in int nWidth, __in int nHeight, __in BOOL bRepaint);
typedef BOOL (WINAPI* PENTRY_GetClientRect)(__in HWND hWnd, __out LPRECT lpRect);
typedef BOOL (WINAPI* PENTRY_SetWindowTextA)(__in HWND hWnd, __in_opt LPCSTR lpString);

PENTRY_GetProcAddress gEntryGetProcAddress = NULL;
PENTRY_FindWindowExA  gEntryFindWindowExA = NULL;
PENTRY_GetModuleHandleA gEntryGetModuleHandleA = NULL;
PENTRY_GetWindowThreadProcessId gEntryGetWindowThreadProcessId = NULL;
PENTRY_GetCurrentProcessId gEntryGetCurrentProcessId = NULL;
PENTRY_GetWindowTextA gEntryGetWindowTextA = NULL;
PENTRY_SendMessageA gEntrySendMessageA = NULL;
PENTRY_GetWindowRect gEntryGetWindowRect = NULL;
PENTRY_PostMessageA gEntryPostMessageA = NULL;
PENTRY_GetClassNameA gEntryGetClassNameA = NULL;
PENTRY_ShowWindow gEntryShowWindow = NULL;
PENTRY_MoveWindow gEntryMoveWindow = NULL;
PENTRY_GetClientRect gEntryGetClientRect = NULL;
PENTRY_SetWindowTextA gEntrySetWindowTextA = NULL;

void __stdcall InitOnce(void* plpGetProcAddress)
{
        HMODULE phKernel32 = 0;
        gEntryGetProcAddress = (PENTRY_GetProcAddress)plpGetProcAddress;
        __asm{
                        mov                eax,plpGetProcAddress
                        shr                eax,16
                        shl                eax,16
                        add                eax,0x10000
CheckNext:
                        sub                eax,0x10000
                        cmp                word ptr [eax],IMAGE_DOS_SIGNATURE
                        jnz                CheckNext
                        mov                phKernel32,eax
        }
        static bool gOnce = false;
        if (!gOnce)
        {
                gOnce = true;
                gEntryGetModuleHandleA = (PENTRY_GetModuleHandleA)gEntryGetProcAddress(phKernel32,"GetModuleHandleA");
                HMODULE phUser32 = gEntryGetModuleHandleA("user32.dll");
                gEntryFindWindowExA        = (PENTRY_FindWindowExA)gEntryGetProcAddress(phUser32,"FindWindowExA");
                gEntryGetWindowThreadProcessId = (PENTRY_GetWindowThreadProcessId)gEntryGetProcAddress(phUser32,"GetWindowThreadProcessId");
                gEntryGetCurrentProcessId = (PENTRY_GetCurrentProcessId)gEntryGetProcAddress(phKernel32,"GetCurrentProcessId");
                gEntryGetWindowTextA = (PENTRY_GetWindowTextA)gEntryGetProcAddress(phUser32,"GetWindowTextA");
                gEntrySendMessageA = (PENTRY_SendMessageA)gEntryGetProcAddress(phUser32,"SendMessageA");
                gEntryPostMessageA = (PENTRY_PostMessageA)gEntryGetProcAddress(phUser32,"PostMessageA");
                gEntryGetWindowRect = (PENTRY_GetWindowRect)gEntryGetProcAddress(phUser32,"GetWindowRect");
                gEntryGetClassNameA = (PENTRY_GetClassNameA)gEntryGetProcAddress(phUser32,"GetClassNameA");
                gEntryShowWindow = (PENTRY_ShowWindow)gEntryGetProcAddress(phUser32,"ShowWindow");
                gEntryMoveWindow = (PENTRY_MoveWindow)gEntryGetProcAddress(phUser32,"MoveWindow");
                gEntryGetClientRect = (PENTRY_GetClientRect)gEntryGetProcAddress(phUser32,"GetClientRect");
                gEntrySetWindowTextA = (PENTRY_SetWindowTextA)gEntryGetProcAddress(phUser32,"SetWindowTextA");
               
        }
}
void __stdcall AutoIt()
{
        HWND phNext = 0;
        do
        {
                phNext = gEntryFindWindowExA(NULL,phNext,NULL,NULL);
                DWORD pdwPID = 0;
                gEntryGetWindowThreadProcessId(phNext,&pdwPID);
                if (pdwPID == gEntryGetCurrentProcessId())
                {
                        char pNText[MAX_PATH];
                        gEntryGetWindowTextA(phNext,pNText,MAX_PATH);
                        if (strcmp(pNText,"FlashBoot") == 0)
                        {
                                HWND phCNext = 0;
                                do
                                {
                                        phCNext = gEntryFindWindowExA(phNext,phCNext,NULL,NULL);
                                        gEntryGetWindowTextA(phCNext,pNText,MAX_PATH);
                                        if (strcmp(pNText,"&Next >") == 0)
                                        {
                                                HWND phCCNext = 0;
                                                do
                                                {
                                                        phCCNext = gEntryFindWindowExA(phNext,phCCNext,"wxWindowClass",NULL);
                                                        HWND phCCCNext = 0;
                                                        do
                                                        {
                                                                phCCCNext = gEntryFindWindowExA(phCCNext,phCCCNext,NULL,NULL);
                                                                gEntryGetWindowTextA(phCCCNext,pNText,MAX_PATH);
                                                                if (strcmp(pNText,"Save data on disk (avoid reformatting)") == 0)
                                                                {
                                                                        gEntrySendMessageA(phCCCNext,BM_SETCHECK,0,0);
                                                                        break;
                                                                }
                                                        } while(phCCCNext);
                                                        if (phCCCNext)
                                                                break;
                                                } while(phCCNext);

                                                gEntryPostMessageA(phCNext,WM_LBUTTONDOWN,MK_LBUTTON,MAKELONG(5,5));
                                                gEntryPostMessageA(phCNext,WM_LBUTTONUP,MK_LBUTTON,MAKELONG(5,5));
                                                gEntryPostMessageA(phCNext,WM_LBUTTONDOWN,MK_LBUTTON,MAKELONG(5,5));
                                                gEntryPostMessageA(phCNext,WM_LBUTTONUP,MK_LBUTTON,MAKELONG(5,5));
                                                break;
                                        }
                                } while(phCNext);
                                break;
                        }
                }
        } while(phNext);

}

void __stdcall FixWindowPos()
{
        HWND phNext = 0;
        do
        {
                phNext = gEntryFindWindowExA(NULL,phNext,NULL,NULL);
                DWORD pdwPID = 0;
                gEntryGetWindowThreadProcessId(phNext,&pdwPID);
                if (pdwPID == gEntryGetCurrentProcessId())
                {
                        char pNText[MAX_PATH];
                        char pNClass[MAX_PATH];
                        gEntryGetWindowTextA(phNext,pNText,MAX_PATH);
                        if (strcmp(pNText,"FlashBoot") == 0)
                        {
                                RECT prccWnd;
                                gEntryGetWindowRect(phNext,&prccWnd);
                                gEntryMoveWindow(phNext,prccWnd.left,prccWnd.top,335,180,TRUE);
                                HWND phCNext = 0;

                                do
                                {
                                        phCNext = gEntryFindWindowExA(phNext,phCNext,NULL,NULL);
                                        gEntryGetWindowTextA(phCNext,pNText,sizeof(pNText));
                                        gEntryGetClassNameA(phCNext,pNClass,sizeof(pNClass));
                                        if (strcmp(pNText,"&Next >") == 0)
                                        {
                                                gEntryGetClientRect(phCNext,&prccWnd);
                                                gEntryMoveWindow(phCNext,130,111,prccWnd.right-prccWnd.left,prccWnd.bottom-prccWnd.top,TRUE);
                                        }else if (strcmp(pNText,"&Cancel") == 0)
                                        {
                                                gEntryGetClientRect(phCNext,&prccWnd);
                                                gEntryMoveWindow(phCNext,230,111,prccWnd.right-prccWnd.left,prccWnd.bottom-prccWnd.top,TRUE);
                                        }else if (strcmp(pNClass,"wxWindowClass") == 0)
                                        {
                                               
                                                //gEntryGetWindowRect(phNext,&prcwxWnd);
                                                gEntryGetClientRect(phCNext,&prccWnd);
                                                gEntryMoveWindow(phCNext,5,-20,prccWnd.right-prccWnd.left,130,TRUE);
                                                HWND phCCNext = 0;
                                                do
                                                {
                                                        phCCNext = gEntryFindWindowExA(phCNext,phCCNext,NULL,NULL);
                                                        gEntryGetWindowTextA(phCCNext,pNText,sizeof(pNText));
                                                        gEntryGetClassNameA(phCCNext,pNClass,sizeof(pNClass));
                                                        if (strcmp(pNClass,"Button") == 0)
                                                        {
                                                                if (strcmp(pNText,"Image file") == 0)
                                                                {
                                                                        gEntryShowWindow(phCCNext,SW_HIDE);
                                                                }else if (strcmp(pNText,"Write bootable USB Flash Disk &image to file") == 0)
                                                                {
                                                                        gEntryShowWindow(phCCNext,SW_HIDE);
                                                                }else if (strcmp(pNText,"Make bootable USB Flash &Disk which is physically present on this PC") == 0)
                                                                {
                                                                        gEntrySetWindowTextA(phCCNext,"Choose USB Flash &Disk-->");
                                                                        gEntryGetClientRect(phCCNext,&prccWnd);
                                                                        gEntryMoveWindow(phCCNext,10,50,200,prccWnd.bottom-prccWnd.top,TRUE);
                                                                }else if (strcmp(pNText,"Local disk drive") == 0)
                                                                {
                                                                        gEntryGetClientRect(phCCNext,&prccWnd);
                                                                        gEntryMoveWindow(phCCNext,0,30,320,90,TRUE);
                                                                }
                                                        }else if (strcmp(pNClass,"Edit") == 0)
                                                        {
                                                                gEntryShowWindow(phCCNext,SW_HIDE);
                                                        }else if (strcmp(pNClass,"Static") == 0)
                                                        {
                                                                if (strcmp(pNText,"Specify the name of target image file here:") == 0)
                                                                {
                                                                        gEntryShowWindow(phCCNext,SW_HIDE);
                                                                }
                                                        }
                                                } while(phCCNext);
                                        }else if (strcmp(pNClass,"Static") == 0)
                                        {
                                                gEntryShowWindow(phCNext,SW_HIDE);
                                        }
                                } while(phCNext);
                                break;
                        }
                }
        } while(phNext);
}

void __declspec(naked) InitWindow()
{
        __asm
        {
                pushad
                mov                eax,0x4DC3D4
                push        [eax]
                call        InitOnce
                call        FixWindowPos
                popad
                mov     eax, dword ptr [esi]
                mov     ecx, esi
                call    dword ptr [eax+0x23C]
                push        0x452729
                ret

        }
}

void __declspec(naked) Entry()
{
        __asm
        {
                push        eax
                push        ecx
                mov                ecx,[esp+0x18]
                mov                eax,[ecx+0x190]
                cmp                eax,[ecx+0x1DC]
                pop                ecx
                pop                eax
                jnz                lab_Normal
                pushad
                mov                eax,0x4DC3D4
                push        [eax]
                call        InitOnce
                call        AutoIt
                popad
lab_Normal:
                pop     esi
                pop     ebp
                retn    4
                mov                eax,InitWindow
        }
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 7
支持
分享
最新回复 (7)
雪    币: 108
活跃值: (42)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
高...
怪不得我看不懂.....

学习
2008-3-5 17:08
0
雪    币: 44229
活跃值: (19960)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
3
编辑了一下你的帖子,把前面几张图放上了。
2008-3-5 17:17
0
雪    币: 398
活跃值: (343)
能力值: (RANK:650 )
在线值:
发帖
回帖
粉丝
4
壳盲写Zprotect
2008-3-5 17:21
0
雪    币: 248
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
5
好文章!我的天,好久我才能赶上你们哦
2008-3-5 17:42
0
雪    币: 221
活跃值: (2256)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
壳盲写Zprotect ??????
2008-3-6 00:06
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
7
由于我是壳盲
2008-3-6 01:08
0
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
8
所以是某兄给我的脱壳后的文件
2008-3-6 12:21
0
游客
登录 | 注册 方可回帖
返回
//