Terrorblade 发表于 2015-2-1 15:43

Visual Assist 10.8.2029.0破解分析

本帖最后由 Terrorblade 于 2015-2-2 12:34 编辑

    Terrorblade这个id在2014年光棍节的时候申请了,但是因为当时没有及时发帖,所以……http://www.52pojie.cn/static/image/smiley/laohu/laohu4.gif,如今失而复得,真是感慨万千呀!

         本文源自看雪http://bbs.pediy.com/showthread.php?t=196284,嗯,版权当然是我本人的,因为我本人水平不是很高,但又不愿写一些bp MessageBox || bp GetDlgItemText之类的破解文章,那样太千篇一律了,所以便有了下面这篇破文,本文并非直接破解Visual Assist 10.8.2029.0,而是通过分析他的patch,最终绕道破解的(附加的视频也已验证,我的手法是正确的)。好了,废话有点多,下面进入正文,若有错误,请各位看官批评指正!

先在“Enter Key”对话框中随意输入一段字符,然后弹出如下对话框:


接着打开任务管理器,打算找到VA的进程,然后附加到OD的,但是任务管理器里没有找到VA的独立进程,只有VS的进程:

那么这个破解思路就断在这里了,出师不利……{:301_1008:}

接着找到对应的破解补丁,如下图:


在打上这个patch之后,VA就算破解完成了,而我们也可以观察到,打上了这个补丁之后,“Enter Key”对话框里仍然留白,并且在VA目录--“C:\Users\Binky\AppData\Local\Microsoft\VisualStudio\10.0\Extensions\WholeTomato Software\Visual Assist\10.8.2029.0”里多出一个文件:
因为在用这个补丁之前,我之前用过其他版本的补丁,以前用的补丁都是要送入到VA的安装目录然后再点击安装才能成功,否则提示无法找到VA的安装目录,此补丁也有”search file manually”,由此可以推断,破解是通过修改并替换掉VA_X.dll达到的!

先来脱壳,先前说了,ASPack2.12 -> Alexey Solodovnikov不足为惧,脱壳很简单,用esp定律就ok了:

脱壳之后,发现代码还算容易阅读(没有什么垃圾代码和乱跳的填充),但是看到”About”按钮后有一点疑惑:



后来去找了工具,发现确实没有穿山甲的保护:


先来看看程序起始的地方:
       0047048C >55               push ebp
0047048D    8BEC               mov ebp,esp
0047048F    83C4 F0            add esp,-10
00470492    B8 D4024700      mov eax,dumped_.004702D4
00470497    E8 A861F9FF      call dumped_.00406644
0047049C    A1 14F74700      mov eax,dword ptr ds:
004704A1    8B00               mov eax,dword ptr ds:
004704A3    E8 8C73FEFF      call dumped_.00457834
004704A8    A1 14F74700      mov eax,dword ptr ds:
004704AD    8B00               mov eax,dword ptr ds:
004704AF    BA EC044700      mov edx,dumped_.004704EC             ; ASCII "Visual Assist X - Patch by BRD"
004704B4    E8 7B6FFEFF      call dumped_.00457434
004704B9    8B0D 04F84700      mov ecx,dword ptr ds:      ; dumped_.00492DEC
004704BF    A1 14F74700      mov eax,dword ptr ds:
004704C4    8B00               mov eax,dword ptr ds:
004704C6    8B15 10EA4600      mov edx,dword ptr ds:      ; dumped_.0046EA5C
004704CC    E8 7B73FEFF      call dumped_.0045784C                ; CreateForm
004704D1    A1 14F74700      mov eax,dword ptr ds:
004704D6    8B00               mov eax,dword ptr ds:
004704D8    E8 EF73FEFF      call dumped_.004578CC                ; Run
004704DD    E8 9E41F9FF      call dumped_.00404680                ; Halt0
在004704CC处有个CreateForm,给后面的调试带来不小麻烦,没办法,屏幕小被遮住了!在004704D8处F7至004578CC

在ida中跟进,来感受一下,这个004578CC有多少个”Xrefsfrom”:

嗯,有点复杂,但是这是个delphi程序,通过找到按钮事件可以节省我们很多时间!

用DeDe载入dumped_,转存后点击”过程—事件”,如下图:

btnPatchClick的rva为0046f334,直接在ida中”G”,跟到0046f334,这里就是关键的按钮事件的起始地址了!
这里先说说这个0046F334   _TForm1_btnPatchClick的基本功能,基本上就是定位安装了va的当前的vs版本,然后为其打上补丁,我安装的vs2010,所以我待会儿走流程分析的时候我就只分析vs2010这个分支,其他的分支都大同小异,他的功能就是patch里所描述的那样:


** Locating VS 6.0-2008 installation **
--------------------------------------------------------
VS 6.0-2008 not found...
Done...


** Locating VS 2010 installation **
--------------------------------------------------------
C:\Users\Binky\AppData\Local\Microsoft\VisualStudio\10.0\Extensions\Whole Tomato Software\Visual Assist\10.8.2029.0\VA_X.dll
ERROR: CRC missmatch. Wrong version?
Done...


** Locating VS 2012 installation **
--------------------------------------------------------
VS 2012 not found...
Done...


** Locating VS 2013 installation **
--------------------------------------------------------
VS 2013 not found...
Done...

我这里已经打过补丁了,所以会提示”ERROR: CRC missmatch. Wrong version?”顺带也附上sub_0046F334的概览图:


在调试的过程中无法得到即时回馈:


下面来调试dumped_文件,在0046F334F2下断,shift+F9后点击Patch按钮,就停下来了,前面是vc++6.0—vs2008版本的补丁段,我这里直接F4到0046f4ff,这里是给VS2010打补丁的段落:


       0046F4FF    8B45 FC         mov eax,dword ptr ss:   ; VS2010 处
0046F502    8B80 2C030000   mov eax,dword ptr ds:
0046F508    8B80 20020000   mov eax,dword ptr ds:
0046F50E    33D2            xor edx,edx                      ; 清零
0046F510    8B08            mov ecx,dword ptr ds:
0046F512    FF51 38         call dword ptr ds:
0046F515    8B45 FC         mov eax,dword ptr ss:
0046F518    8B80 2C030000   mov eax,dword ptr ds:
0046F51E    8B80 20020000   mov eax,dword ptr ds:
0046F524    33D2            xor edx,edx
0046F526    8B08            mov ecx,dword ptr ds:
0046F528    FF51 38         call dword ptr ds:
0046F52B    8B45 FC         mov eax,dword ptr ss:
0046F52E    8B80 2C030000   mov eax,dword ptr ds:
0046F534    8B80 20020000   mov eax,dword ptr ds:
0046F53A    BA 74FB4600   mov edx,dumped_.0046FB74         ; 定位"** Locating VS 2010 installation **"
0046F53F    8B08            mov ecx,dword ptr ds:
0046F541    FF51 38         call dword ptr ds:
0046F544    8B45 FC         mov eax,dword ptr ss:
0046F547    8B80 2C030000   mov eax,dword ptr ds:
0046F54D    8B80 20020000   mov eax,dword ptr ds:
0046F553    BA A4FA4600   mov edx,dumped_.0046FAA4         ; 华丽的分割线
0046F558    8B08            mov ecx,dword ptr ds:
0046F55A    FF51 38         call dword ptr ds:
0046F55D    B2 01         mov dl,1
0046F55F    A1 88E44600   mov eax,dword ptr ds:
0046F564    E8 1FF0FFFF   call dumped_.0046E588            ; Registry::TRegistry::TRegistry(void)
0046F569    8945 EC         mov dword ptr ss:,eax
0046F56C    BA 01000080   mov edx,80000001
0046F571    8B45 EC         mov eax,dword ptr ss:
0046F574    E8 AFF0FFFF   call dumped_.0046E628            ; Registry::TRegistry::SetRootKey(uint)
0046F579    33C9            xor ecx,ecx
0046F57B    BA A0FB4600   mov edx,dumped_.0046FBA0         ; 注册表路径--"SOFTWARE\Microsoft\VisualStudio\10.0\ExtensionManager\EnabledExtensions"
0046F580    8B45 EC         mov eax,dword ptr ss:
0046F583    E8 04F1FFFF   call dumped_.0046E68C            ; Registry::TRegistry::OpenKey(System::AnsiString,bool)
0046F588    84C0            test al,al
0046F58A    0F84 8A000000   je dumped_.0046F61A
0046F590    8D4D E4         lea ecx,dword ptr ss:
0046F593    BA F0FB4600   mov edx,dumped_.0046FBF0         ; 获取注册表键值
0046F598    8B45 EC         mov eax,dword ptr ss:
0046F59B    E8 B4F2FFFF   call dumped_.0046E854            ; Registry::TRegistry::ReadString(System::AnsiString)
0046F5A0    837D E4 00      cmp dword ptr ss:,0      ; purge
0046F5A4    74 74         je short dumped_.0046F61A
0046F5A6    BA F0FB4600   mov edx,dumped_.0046FBF0         ; "44630d46-96b5-488c-8df926e21db8c1a3,10.8.2029.0"
0046F5AB    8D4D F8         lea ecx,dword ptr ss:
0046F5AE    8B45 EC         mov eax,dword ptr ss:    ; C:\Users\Binky\AppData\Local\Microsoft\VisualStudio\10.0\Extensions\Whole Tomato Software\Visual Assist\10.8.2029.0\
0046F5B1    E8 9EF2FFFF   call dumped_.0046E854            ; Registry::TRegistry::ReadString(System::AnsiString)
0046F5B6    8D45 F8         lea eax,dword ptr ss:
0046F5B9    BA 28FC4600   mov edx,dumped_.0046FC28         ; "VA_X.dll"
0046F5BE    E8 7D54F9FF   call dumped_.00404A40            ; System::__linkproc__ LStrCat(void)
0046F5C3    8B45 FC         mov eax,dword ptr ss:
0046F5C6    8B80 2C030000   mov eax,dword ptr ds:
0046F5CC    8B80 20020000   mov eax,dword ptr ds:
0046F5D2    8B55 F8         mov edx,dword ptr ss:
0046F5D5    8B08            mov ecx,dword ptr ds:
0046F5D7    FF51 38         call dword ptr ds:
0046F5DA    8D4D F0         lea ecx,dword ptr ss:
0046F5DD    8B55 F4         mov edx,dword ptr ss:   ; "BINKY-PC"
0046F5E0    8B45 F8         mov eax,dword ptr ss:   ; "C:\Users\Binky\AppData\Local\Microsoft\VisualStudio\10.0\Extensions\Whole Tomato Software\Visual Assist\10.8.2029.0\VA_X.dll"
0046F5E3    E8 64F9FFFF   call dumped_.0046EF4C            ; 关键call,各版本VS都是用此函数来修改VA_X

获取注册表键值:

之前看到过44630d46-96b5-488c-8df926e21db8c1a3这个字符串,以为是注册码……{:301_983:}
我对delphi不是很了解,就是百度了也找不到相关API函数的详细解释,所以在阅读代码的时候遇到有关delphi的api函数就见名知意吧,在0046F5E3就是关键call了,F7进去:
       0046EF4C    55            push ebp
0046EF4D    8BEC            mov ebp,esp
0046EF4F    81C4 9CFEFFFF   add esp,-164
0046EF55    53            push ebx
0046EF56    56            push esi
0046EF57    57            push edi
0046EF58    33DB            xor ebx,ebx
0046EF5A    899D 9CFEFFFF   mov dword ptr ss:,ebx
0046EF60    895D F0         mov dword ptr ss:,ebx
0046EF63    894D F4         mov dword ptr ss:,ecx
0046EF66    8955 F8         mov dword ptr ss:,edx   ; BINKY-PC

0046EF69    8945 FC         mov dword ptr ss:,eax   ; "C:\Users\Binky\AppData\Local\Microsoft\VisualStudio\10.0\Extensions\Whole Tomato Software\Visual Assist\10.8.2029.0\VA_X.dll"
0046EF6C    8B45 FC         mov eax,dword ptr ss:

0046EF6F    E8 B45CF9FF   call dumped_.00404C28            ; 没找到相关说明System::__linkproc__ LStrAddRef(void *)
0046EF74    8B45 F8         mov eax,dword ptr ss:

0046EF77    E8 AC5CF9FF   call dumped_.00404C28            ; System::__linkproc__ LStrAddRef(void *)
0046EF7C    33C0            xor eax,eax                      ; 用完清零
0046EF7E    55            push ebp
0046EF7F    68 9DF14600   push dumped_.0046F19D
0046EF84    64:FF30         push dword ptr fs:
0046EF87    64:8920         mov dword ptr fs:,esp
0046EF8A    33D2            xor edx,edx
0046EF8C    55            push ebp
0046EF8D    68 35F14600   push dumped_.0046F135
0046EF92    64:FF32         push dword ptr fs:
0046EF95    64:8922         mov dword ptr fs:,esp
0046EF98    8D55 EC         lea edx,dword ptr ss:
0046EF9B    8B45 FC         mov eax,dword ptr ss:
0046EF9E    E8 39FEFFFF   call dumped_.0046EDDC            ;
0046EFA3    A1 14F74700   mov eax,dword ptr ds:
0046EFA8    8B00            mov eax,dword ptr ds:

0046EFAA    E8 7987FEFF   call dumped_.00457728            ; Forms::TApplication::HandleMessage(void)
0046EFAF    8B45 EC         mov eax,dword ptr ss:
0046EFB2    33D2            xor edx,edx
0046EFB4    52            push edx
0046EFB5    50            push eax
0046EFB6    8D95 9CFEFFFF   lea edx,dword ptr ss:
0046EFBC    B8 06000000   mov eax,6
0046EFC1    E8 8A9AF9FF   call dumped_.00408A50            ; Sysutils::IntToHex(__int64,int)
0046EFC6    8B85 9CFEFFFF   mov eax,dword ptr ss:   ; "CA398E13" ?
0046EFCC    BA B4F14600   mov edx,dumped_.0046F1B4         ; "FE4274C7" ?
0046EFD1    E8 AE5BF9FF   call dumped_.00404B84            ; System::__linkproc__ LStrCmp(void)
0046EFD6    0F85 2D010000   jnz dumped_.0046F109
0046EFDC    8D45 F0         lea eax,dword ptr ss:
0046EFDF    B9 C8F14600   mov ecx,dumped_.0046F1C8         ; ASCII ".bak"
0046EFE4    8B55 FC         mov edx,dword ptr ss:

0046EFE7    E8 985AF9FF   call dumped_.00404A84            ; System::__linkproc__ LStrCat3(void)
0046EFEC    8B45 F0         mov eax,dword ptr ss:

0046EFEF    E8 389EF9FF   call dumped_.00408E2C            ; 判断文件是否存在 Sysutils::FileExists(System::AnsiString)
0046EFF4    84C0            test al,al
0046EFF6    75 19         jnz short dumped_.0046F011       ; 为了看流程 zf=0
0046EFF8    6A 00         push 0                           ; bFailIfExists
0046EFFA    8B45 F0         mov eax,dword ptr ss:

0046EFFD    E8 365CF9FF   call dumped_.00404C38            ; System::__linkproc__ LStrToPChar(System::AnsiString)

0046F002    50            push eax                         ; lpNewFileName --"C:\Users\Binky\AppData\Local\Microsoft\VisualStudio\10.0\Extensions\Whole Tomato Software\Visual Assist\10.8.2029.0\VA_X.dll.bak"
0046F003    8B45 FC         mov eax,dword ptr ss:   ; eax存着".../VA_X.dll.bak",ss:中存着".../VA_X.dll"
0046F006    E8 2D5CF9FF   call dumped_.00404C38

0046F00B    50            push eax                         ; lpExistingFileName--".../VA_X.dll"

0046F00C    E8 3378F9FF   call <jmp.&kernel32.CopyFileA>   ; CopyFileA把原来的VA_X.dll拷贝一份并改名VA_X.dll.bak
0046F011    8B55 FC         mov edx,dword ptr ss:

0046F014    8D85 A0FEFFFF   lea eax,dword ptr ss:

0046F01A    E8 713FF9FF   call dumped_.00402F90            ; System::__linkproc__ Assign(System::TTextRec &,System::AnsiString)
0046F01F    A1 94F74700   mov eax,dword ptr ds:
0046F024    C600 01         mov byte ptr ds:,1
0046F027    BA 01000000   mov edx,1
0046F02C    8D85 A0FEFFFF   lea eax,dword ptr ss:

0046F032    E8 9D43F9FF   call dumped_.004033D4            ; System::__linkproc__ ResetFile(System::TFileRec &,int)

0046F037    E8 B83BF9FF   call dumped_.00402BF4            ; System::__linkproc__ _IOTest(void)
0046F03C    BA C7731400   mov edx,1473C7
0046F041    8D85 A0FEFFFF   lea eax,dword ptr ss:
0046F047    E8 A443F9FF   call dumped_.004033F0            ; 这里是寻找写入地址,和写入的整数个字符的数量System::__linkproc__ Seek(System::TFileRec &,uint)
0046F04C    E8 A33BF9FF   call dumped_.00402BF4
0046F051    6A 00         push 0
0046F053    BA 242B4700   mov edx,dumped_.00472B24         ; "l\n"
0046F058    B9 07000000   mov ecx,7
0046F05D    8D85 A0FEFFFF   lea eax,dword ptr ss:

0046F063    E8 A040F9FF   call dumped_.00403108            ; 这里开始写入VA_X.dllSystem::__linkproc__ BlockWrite(System::TFileRec &,void *,int,int &)
0046F068    E8 873BF9FF   call dumped_.00402BF4
0046F06D    BA 00201E00   mov edx,1E2000
0046F072    8D85 A0FEFFFF   lea eax,dword ptr ss:

0046F078    E8 7343F9FF   call dumped_.004033F0            ; System::__linkproc__ Seek(System::TFileRec &,uint)

0046F07D    E8 723BF9FF   call dumped_.00402BF4            ; System::__linkproc__ _IOTest(void)
0046F082    6A 00         push 0
0046F084    BA 2C2B4700   mov edx,dumped_.00472B2C
0046F089    B9 BA000000   mov ecx,0BA
0046F08E    8D85 A0FEFFFF   lea eax,dword ptr ss:

0046F094    E8 6F40F9FF   call dumped_.00403108            ; System::__linkproc__ BlockWrite(System::TFileRec &,void *,int,int &)

0046F099    E8 563BF9FF   call dumped_.00402BF4            ; System::__linkproc__ _IOTest(void)
0046F09E    8D85 A0FEFFFF   lea eax,dword ptr ss:

0046F0A4    E8 7F40F9FF   call dumped_.00403128            ; System::__linkproc__ Close(System::TTextRec &)
0046F0A9    E8 463BF9FF   call dumped_.00402BF4
0046F0AE    B2 01         mov dl,1
0046F0B0    A1 88E44600   mov eax,dword ptr ds:

0046F0B5    E8 CEF4FFFF   call dumped_.0046E588            ; Registry::TRegistry::TRegistry(void)
0046F0BA    8BD8            mov ebx,eax
0046F0BC    BA 01000080   mov edx,80000001
0046F0C1    8BC3            mov eax,ebx
0046F0C3    E8 60F5FFFF   call dumped_.0046E628
0046F0C8    B1 01         mov cl,1

0046F0CA    BA D8F14600   mov edx,dumped_.0046F1D8         ; ASCII "SOFTWARE\Whole Tomato\Visual Assist X"
0046F0CF    8BC3            mov eax,ebx

0046F0D1    E8 B6F5FFFF   call dumped_.0046E68C            ; Registry::TRegistry::OpenKey(System::AnsiString,bool)
0046F0D6    84C0            test al,al
0046F0D8    74 20         je short dumped_.0046F0FA

0046F0DA    8B4D F8         mov ecx,dword ptr ss:   ; "BINKY-PC"
0046F0DD    BA 08F24600   mov edx,dumped_.0046F208         ; ASCII "UserName"
0046F0E2    8BC3            mov eax,ebx                      ; "*@"
0046F0E4    E8 3FF7FFFF   call dumped_.0046E828            ; "BINKY-PC"和"UserName"匹配--Registry::TRegistry::WriteString(System::AnsiString,System::AnsiString)

0046F0E9    B9 1CF24600   mov ecx,dumped_.0046F21C         ; ASCII "You will never defeat the riddle of the Black Riders..."
0046F0EE    BA 5CF24600   mov edx,dumped_.0046F25C         ; ASCII "UserKey"
0046F0F3    8BC3            mov eax,ebx

0046F0F5    E8 2EF7FFFF   call dumped_.0046E828            ; Registry::TRegistry::WriteString(System::AnsiString,System::AnsiString)
0046F0FA    8B45 F4         mov eax,dword ptr ss:

0046F0FD    BA 6CF24600   mov edx,dumped_.0046F26C         ; ASCII "SUCCESS: File patched successfully!"

0046F102    E8 C556F9FF   call dumped_.004047CC            ; System::__linkproc__ LStrAsg(void *,void *)
0046F107    EB 22         jmp short dumped_.0046F12B
0046F109    837D EC 00      cmp dword ptr ss:,0
0046F10D    75 0F         jnz short dumped_.0046F11E
0046F10F    8B45 F4         mov eax,dword ptr ss:

0046F112    BA 98F24600   mov edx,dumped_.0046F298         ; ASCII "ERROR: File does not exist..."
0046F117    E8 B056F9FF   call dumped_.004047CC
0046F11C    EB 0D         jmp short dumped_.0046F12B
0046F11E    8B45 F4         mov eax,dword ptr ss:

0046F121    BA C0F24600   mov edx,dumped_.0046F2C0         ; ASCII "ERROR: CRC missmatch. Wrong version?"
0046F126    E8 A156F9FF   call dumped_.004047CC
0046F12B    33C0            xor eax,eax
0046F12D    5A            pop edx
0046F12E    59            pop ecx
0046F12F    59            pop ecx
0046F130    64:8910         mov dword ptr fs:,edx
0046F133    EB 3A         jmp short dumped_.0046F16F
0046F135^ E9 924EF9FF   jmp dumped_.00403FCC
0046F13A    0200            add al,byte ptr ds:
0046F13C    0000            add byte ptr ds:,al

0046F13E    D878 40         fdivr dword ptr ds:
0046F141    004E F1         add byte ptr ds:,cl
0046F144    46            inc esi
0046F145    0000            add byte ptr ds:,al
0046F147    0000            add byte ptr ds:,al
0046F149    005D F1         add byte ptr ss:,bl
0046F14C    46            inc esi
0046F14D    008B 45F4BAF0   add byte ptr ds:,c>
0046F153    F2:             prefix repne:
0046F154    46            inc esi
0046F155    00E8            add al,ch
0046F157    71 56         jno short dumped_.0046F1AF
0046F159    F9            stc
0046F15A    FFEB            jmp far ebx                      ; 非法使用寄存器
0046F15C    0D 8B45F4BA   or eax,BAF4458B
0046F161    1C F3         sbb al,0F3
0046F163    46            inc esi
0046F164    00E8            add al,ch
0046F166    6256 F9         bound edx,qword ptr ds:
0046F169    FFE8            jmp far eax                      ; 非法使用寄存器
0046F16B    99            cdq
0046F16C    50            push eax
0046F16D    F9            stc
0046F16E    FF33            push dword ptr ds:
0046F170    C05A 59 59      rcr byte ptr ds:,59
0046F174    64:8910         mov dword ptr fs:,edx
0046F177    68 A4F14600   push dumped_.0046F1A4
0046F17C    8D85 9CFEFFFF   lea eax,dword ptr ss:

0046F182    E8 F155F9FF   call dumped_.00404778            ; System::__linkproc__ LStrClr(void *)
0046F187    8D45 F0         lea eax,dword ptr ss:

0046F18A    E8 E955F9FF   call dumped_.00404778            ; System::__linkproc__ LStrClr(void *)
0046F18F    8D45 F8         lea eax,dword ptr ss:
0046F192    BA 02000000   mov edx,2

0046F197    E8 0056F9FF   call dumped_.0040479C            ; System::__linkproc__ LStrArrayClr(void *,int)
0046F19C    C3            retn在0046F047 有个seek函数、0046F063 BlockWrite,还有就是0046F078-seek和0046F094-BlockWrite,seek函数调用了Kernel32.SetFilePointer(),以设置当前的读写位置,然后在BlockWrite()就很显而易见,不猜都能知道他Hook了Kernel32.WriteFile()来改写VA_X.dll,因为很多感染型病毒都是这样来修改文件的,下面来看看0046F047-Seek():
      004033F0    89C1            mov ecx,eax                  
004033F2    0FB740 04       movzx eax,word ptr ds:
004033F6    2D B1D70000   sub eax,0D7B1
004033FB    83F8 02         cmp eax,2
004033FE    77 19         ja short dumped_.00403419
00403400    6A 00         push 0                         ; dwMoveMethod
00403402    8B41 08         mov eax,dword ptr ds:
00403405    F7E2            mul edx
00403407    6A 00         push 0                         ; lpDistanceToMoveHigh
00403409    50            push eax                     ; lDistanceToMove
0040340A    FF31            push dword ptr ds:      ; hFile
0040340C    E8 2BDEFFFF   call <jmp.&kernel32.SetFilePoi>
00403411    40            inc eax                        ; 返回+1字节偏移量
00403412^ 0F84 0CF8FFFF   je dumped_.00402C24
00403418    C3            retn他在调用了SetFilePointer()时各参数的值:


0046f063-BlockWrite():
00403108    55            push ebp
00403109    8BEC            mov ebp,esp
0040310B    53            push ebx
0040310C    8B5D 08         mov ebx,dword ptr ss:
0040310F    53            push ebx
00403110    68 B2D70000   push 0D7B2
00403115    68 54304000   push <jmp.&kernel32.WriteFile>
0040311A    6A 65         push 65
0040311C    E8 3BFFFFFF   call dumped_.0040305C
00403121    5B            pop ebx
00403122    5D            pop ebp
00403123    C2 0400         retn 4Hook kernel32.WriteFile后,此处堆栈上个参数的值:

接着看0046F078-Seek():
004033F0    89C1            mov ecx,eax
004033F2    0FB740 04       movzx eax,word ptr ds:
004033F6    2D B1D70000   sub eax,0D7B1
004033FB    83F8 02         cmp eax,2
004033FE    77 19         ja short dumped_.00403419
00403400    6A 00         push 0
00403402    8B41 08         mov eax,dword ptr ds:
00403405    F7E2            mul edx
00403407    6A 00         push 0
00403409    50            push eax
0040340A    FF31            push dword ptr ds:
0040340C    E8 2BDEFFFF   call <jmp.&kernel32.SetFilePoin>
00403411    40            inc eax
00403412^ 0F84 0CF8FFFF   je dumped_.00402C24
00403418    C3            retn
调用SetFilePointer()时堆栈上变量的值:


0046F094-BlockWrite():
00403108    55            push ebp
00403109    8BEC            mov ebp,esp
0040310B    53            push ebx
0040310C    8B5D 08         mov ebx,dword ptr ss:
0040310F    53            push ebx
00403110    68 B2D70000   push 0D7B2
00403115    68 54304000   push <jmp.&kernel32.WriteFile>
0040311A    6A 65         push 65
0040311C    E8 3BFFFFFF   call dumped_.0040305C
00403121    5B            pop ebx
00403122    5D            pop ebp
00403123    C2 0400         retn 4Hookkernel32.WriteFile后,此处堆栈上个参数的值:

一路走过来还算顺利,但是我对delphi不熟悉,所以在写入VA_X.dll这个过程中分析起来很吃力,其实走到这里,含糊一点就可以收官了,因为流程走到下面所示代码,就算分析完成了,代码如下:
0046F047    E8 A443F9FF   call dumped_.004033F0            ; System::__linkproc__ Seek(System::TFileRec &,uint)
0046F04C    E8 A33BF9FF   call dumped_.00402BF4            ; IOTest(void)
0046F051    6A 00         push 0
0046F053    BA 242B4700   mov edx,dumped_.00472B24         ; "l\n"
0046F058    B9 07000000   mov ecx,7
0046F05D    8D85 A0FEFFFF   lea eax,dword ptr ss:

0046F063    E8 A040F9FF   call dumped_.00403108            ; System::__linkproc__ BlockWrite(这里开始写入VA_X.dll System::TFileRec &,void *,int,int &)
0046F068    E8 873BF9FF   call dumped_.00402BF4            ; RuntimeError
0046F06D    BA 00201E00   mov edx,1E2000
0046F072    8D85 A0FEFFFF   lea eax,dword ptr ss:

0046F078    E8 7343F9FF   call dumped_.004033F0            ; System::__linkproc__ Seek(System::TFileRec &,uint)

0046F07D    E8 723BF9FF   call dumped_.00402BF4            ; System::__linkproc__ _IOTest(void)
0046F082    6A 00         push 0
0046F084    BA 2C2B4700   mov edx,dumped_.00472B2C
0046F089    B9 BA000000   mov ecx,0BA
0046F08E    8D85 A0FEFFFF   lea eax,dword ptr ss:

0046F094    E8 6F40F9FF   call dumped_.00403108            ; System::__linkproc__ BlockWrite(System::TFileRec &,void *,int,int &)

0046F099    E8 563BF9FF   call dumped_.00402BF4            ; System::__linkproc__ _IOTest(void)
0046F09E    8D85 A0FEFFFF   lea eax,dword ptr ss:

0046F0A4    E8 7F40F9FF   call dumped_.00403128            ; System::__linkproc__ Close(System::TTextRec &)
就是经过了两个BlockWrite()后,再Close(),在VA安装目录下就马上完成了对VA_X.dll修改:
      
根本就不用管下面的流程:
       0046F0DA    8B4D F8         mov ecx,dword ptr ss:   ; "BINKY-PC"

0046F0DD    BA 08F24600   mov edx,dumped_.0046F208       ; ASCII "UserName"

0046F0E2    8BC3            mov eax,ebx                  ; "*@"

0046F0E4    E8 3FF7FFFF   call dumped_.0046E828          ; 这里写入注册表--Registry::TRegistry::WriteString(System::AnsiString,System::AnsiString)

0046F0E9    B9 1CF24600   mov ecx,dumped_.0046F21C       ; ASCII "You will never defeat the riddle of the Black Riders..."

0046F0EE    BA 5CF24600   mov edx,dumped_.0046F25C       ; ASCII "UserKey"

0046F0F3    8BC3            mov eax,ebx

0046F0F5    E8 2EF7FFFF   call dumped_.0046E828          ; Registry::TRegistry::WriteString(System::AnsiString,System::AnsiString)我本来以为还要往注册表里写入所谓的"UserName"和"UserKey"呢,走完了,才发现,作者只是想开个玩笑--"You will never defeat the riddle of the BlackRiders...",你永远无法解开黑暗骑士之谜,我了个……说到这,那么问题就来了,因为小菜我想用MFC重写这个补丁,但是对delphi的BlockWrite(),只有如下了解:
       delphi BlockWrite(System::TFileRec &,void *,int,int &)

BlockWrite(F2, Buf, NumRead, Numwritten)


procedure BlockWrite(var f: File; var Buf; Count: Integer [; var AmtTransferred: Integer]);

Description

F is an untyped file variable, Buf is any variable, Count is an expression of type Integer, and AmtTransferred is an optional variable of type Integer.

BlockWrite writes Count or fewer records to the file F from memory, starting at the first byte occupied by Buf. The actual number of complete records written (less than or equal to Count) is returned in AmtTransferred.

The entire block transferred occupies at most Count * RecSize bytes. RecSize is the record size specified when the file was opened (or 128 if the record size was unspecified).

If the entire block is transferred, AmtTransferred is equal to Count on return.

If AmtTransferred is less than Count, the disk became full before the transfer was complete. In this case, if the file's record size is greater than 1, AmtTransferred returns the number of complete records written.

BlockWrite advances the current file position by AmtTransferred records.

If AmtTransferred isn't specified, an I/O error occurs if the number written isn't equal to Count. If the $I+ compiler directive is in effect, errors raise an EInOutError exception.大致意思是,BlockWrite从内存写入一定数量字节到文件F,从缓冲区第一个字节开始,真正写入字节的数量存储于第4个参数。
在汇编代码中,并没有找到他push这4个参数,缓冲数据在哪,写入位置在哪,写入的字节数是多少,都找不到,所以要用WriteFile()来改写此补丁的话,我在这里卡了好久!
好,问题在哪就回溯到哪,F7进入第1处BlockWrite():

在ida继续跟进,看看这个dumped_.0040305c有多少个”Xrefsfrom”:

第1处BlockWrite()之后,启动VS就不会再弹出VA的注册框(VA呈灰色),但是在退出VS的时候会出现异常!



说明注册是分两步(两次BlockWrite())来完成的,第一步去除主窗口,第二步完成注册!
第一次,调用WriteFile()的函数在sub_0040305c,如下:
0040305C    55            push ebp                           ; 调用writefile成功

0040305D    8BEC            mov ebp,esp

0040305F    51            push ecx

00403060    53            push ebx

00403061    56            push esi

00403062    57            push edi

00403063    8BF1            mov esi,ecx

00403065    8BFA            mov edi,edx

00403067    8BD8            mov ebx,eax

00403069    8B45 10         mov eax,dword ptr ss:

0040306C    0FB753 04       movzx edx,word ptr ds:

00403070    23D0            and edx,eax

00403072    3BC2            cmp eax,edx

00403074    75 58         jnz short dumped_.004030CE

00403076    6A 00         push 0                           ; lpOverlapped=0,不是以FILE_FLAG_OVERLAPPED方式打开

00403078    8D45 FC         lea eax,dword ptr ss:

0040307B    50            push eax                           ; lpNumberOfBytesWritten=0012F438

0040307C    8B43 08         mov eax,dword ptr ds:

0040307F    F7EE            imul esi

00403081    50            push eax                           ; nNumberOfBytesToWrite=7

00403082    57            push edi                           ; lpBuffer=00472B24

00403083    8B03            mov eax,dword ptr ds:

00403085    50            push eax                           ; hFile=0000025c

00403086    FF55 0C         call dword ptr ss:          ; 00403054 (<jmp.&kernel32.WriteFile>)

00403089    85C0            test eax,eax                     ; eax=00000001 writefile调用成功

0040308B    75 11         jnz short dumped_.0040309E而写入的缓冲数据保存于001473c7的7个byte:
E9346C0A009090   

第二次调用WriteFile(),如下:
0040305C    55            push ebp                         ; 调用writefile成功

0040305D    8BEC            mov ebp,esp
0040305F    51            push ecx
00403060    53            push ebx
00403061    56            push esi
00403062    57            push edi
00403063    8BF1            mov esi,ecx
00403065    8BFA            mov edi,edx
00403067    8BD8            mov ebx,eax
00403069    8B45 10         mov eax,dword ptr ss:
0040306C    0FB753 04       movzx edx,word ptr ds:
00403070    23D0            and edx,eax
00403072    3BC2            cmp eax,edx
00403074    75 58         jnz short dumped_.004030CE
00403076    6A 00         push 0                           ; lpOverlapped=0,不是以FILE_FLAG_OVERLAPPED方式打开
00403078    8D45 FC         lea eax,dword ptr ss:
0040307B    50            push eax                         ; lpNumberOfBytesWritten=0012F438
0040307C    8B43 08         mov eax,dword ptr ds:
0040307F    F7EE            imul esi
00403081    50            push eax                         ; nNumberOfBytesToWrite=BA
00403082    57            push edi                         ; lpBuffer=00472B2C
00403083    8B03            mov eax,dword ptr ds:
00403085    50            push eax                         ; hFile=0000025c
00403086    FF55 0C         call dword ptr ss:      ; 00403054 (<jmp.&kernel32.WriteFile>)
00403089    85C0            test eax,eax                     ; eax=00000001 writefile调用成功
0040308B    75 11         jnz short dumped_.0040309E


而写入的缓冲数据在001E2000的186byte(即 nNumberOfBytesToWrite=BA):609C8B4C242481394F757470751A817904757444657511817908627567537508C744242058406D1F813956697274751A81790475616C507511817908726F74657508C74424208B406D1F9D618945E4837DE400E97493F5FF8B042481781E335114337523C745ECC0BA3066C745E43457866CC745E073B888F5C745DCCD9D2AE0C745D813BB96E833C040C3C644240C40833D0010D01E00741BC705DFC2D81E33C040E9C705E3C2D81E39060000C605316AE01E32FF2534426E1F

只要在winhex里找到001473c7和001E2000这两个地址,并替换成上述所给的数据,即可破解,附送的视频也已验证成功!
       对论坛的功能不是很熟悉,有些东西上传实在太麻烦了,这里一并给出:
       http://pan.baidu.com/s/1mgyvuOg
      文中可能有些地方编辑的不好,原始的word文档打包在rar里,破解的视频的视频也录制好了,放在百度云盘共享里      FB

mxdhqm 发表于 2015-2-9 15:57

楼主牛逼,赞一个

soft30 发表于 2015-2-23 16:09

分析的很透彻, 多谢分享。

ToBeStar 发表于 2015-2-9 20:16

之前一直用Trial-Reset来免除限制,但是30天一次太麻烦了,感谢啊,精华!!!

修文 发表于 2015-2-9 08:13

膜拜大神,先学习了

djinnhao 发表于 2015-2-8 09:50

很好很强大

Terrorblade 发表于 2015-2-1 16:00

快乐海岸线 发表于 2015-2-1 15:51
楼主分析的好透彻啊 赞一个

你也是今天注册的{:301_997:}
你能看到图吗?我用的是长城宽带,验证码什么都不显示,然后开了vpn重新获取验证码,然后图就不见

Hmily 发表于 2015-2-1 17:57

后面的代码怎么都被合并到一起了,从word里直接粘的?你可以试下这个功能,帖子编辑好可以获得精华鼓励!

Terrorblade 发表于 2015-2-1 19:58

重新编好了,终于有图了,话说的宽带问题太麻烦了,不挂vpn就没有验证码,挂了vpn重新编辑这张帖子都卡的{:301_995:}

Hmily 发表于 2015-2-1 21:04

Terrorblade 发表于 2015-2-1 19:58
重新编好了,终于有图了,话说的宽带问题太麻烦了,不挂vpn就没有验证码,挂了vpn重新编辑这张帖子都卡的{: ...

赞,咋弄了2个贴?直接覆盖在主贴上不好?

Terrorblade 发表于 2015-2-1 21:41

Hmily 发表于 2015-2-1 21:04
赞,咋弄了2个贴?直接覆盖在主贴上不好?

不好意思H大,因为在看雪那边好像没有重新编辑的功能,而且在52pojie编辑的帖子真的有点困难,我今天折腾一个了1个小时才注册成功,因为我的长城宽带确实看不到验证码{:301_972:}……我本来以为重新发出来您就把原来的楼移走,我不知道编辑功能在哪呀,另外我是个dota玩家,最近dota亚洲杯,我一编辑又去看比赛了{:301_1008:}

Hmily 发表于 2015-2-1 21:43

Terrorblade 发表于 2015-2-1 21:41
不好意思H大,因为在看雪那边好像没有重新编辑的功能,而且在52pojie编辑的帖子真的有点困难,我今天折腾 ...

牛逼。。。还是dota牛啊!你直接把编辑好的帖子,点击源代码,然后复制到主题贴那个源代码你就可以了。

627853691 发表于 2015-2-2 09:25

楼主分析的好透彻啊 赞一个

Hmily 发表于 2015-2-2 11:27

Terrorblade 发表于 2015-2-1 21:41
不好意思H大,因为在看雪那边好像没有重新编辑的功能,而且在52pojie编辑的帖子真的有点困难,我今天折腾 ...

辛苦了,还有最后一个问题就完美了, 那些图片直接复制不行,必须上传然后指定到原帖处,不然一会就失效了。

Terrorblade 发表于 2015-2-2 12:01

Hmily 发表于 2015-2-2 11:27
辛苦了,还有最后一个问题就完美了, 那些图片直接复制不行,必须上传然后指定到原帖处,不然一会就失效 ...

谢谢H大提醒,小菜我在用word复制的时候就看到图片是复制不了的,后来买了个稳定vpn上传了图片,应该不会失效{:301_977:}
页: [1] 2 3 4 5 6 7
查看完整版本: Visual Assist 10.8.2029.0破解分析