Visual assist 10.8.2029.0 analysis

22
Visual Assist 10.8.2029.0 破破破破破破 破破破破破破破破破破 ,,一一,,,,,! 破破 VS2010 Visual Assist 破 破 VS 破 破 10.8.2029.0 破 破 破 破 ……破 破 ,,() ,! 破破“Enter Key”破 破破 一,: 破破 VA 破 破 OD 破 破 VA 破 破 VS 破破破破 破…… 破破 ,:

Transcript of Visual assist 10.8.2029.0 analysis

Page 1: Visual assist 10.8.2029.0 analysis

Visual Assist 10.8.2029.0破解补丁分析围观看雪已经很久了,只是自己太菜了,一直不敢迈出第一步,前些天找到个机会,

于是就有现在这篇文章,初次发帖,难免有错误,请大家批评指正!

重装电脑,装了 VS2010,相信大家都知道 Visual Assist这款插件,是 VS的必备插件!在网上找到了 10.8.2029.0版本的,算是比较新的版本了,老是找不到对应的破解补丁(后来在国外网站上找到了)……国内的大神都不舍得分享,小菜我只能自己动手了!

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

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

那么这个破解思路就断在这里了,出师不利……

Page 2: Visual assist 10.8.2029.0 analysis

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

在打上这个 patch之后,VA就算破解完成了,而我们也可以观察到,打上了这个补丁之后,“Enter Key”对话框里仍然留白,并且在 VA目录-- “C:\Users\Binky\AppData\Local\Microsoft\VisualStudio\10.0\Extensions\Whole Tomato Software\Visual Assist\10.8.2029.0”里多出一个文件:

因为在用这个补丁之前,我之前用过其他版本的补丁,以前用的补丁都是要送入到 VA的安装目录然后再点击安装才能成功,否则提示无法找到 VA的安装目录,此补丁也有”search file manually”,由此可以推断,破解是通过修改并替换掉 VA_X.dll达到的!

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

Page 3: Visual assist 10.8.2029.0 analysis

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

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

Page 4: Visual assist 10.8.2029.0 analysis

先来看看程序起始的地方:0047048C > 55 push ebp0047048D 8BEC mov ebp,esp0047048F 83C4 F0 add esp,-1000470492 B8 D4024700 mov eax,dumped_.004702D400470497 E8 A861F9FF call dumped_.004066440047049C A1 14F74700 mov eax,dword ptr ds:[47F714]004704A1 8B00 mov eax,dword ptr ds:[eax]004704A3 E8 8C73FEFF call dumped_.00457834004704A8 A1 14F74700 mov eax,dword ptr ds:[47F714]004704AD 8B00 mov eax,dword ptr ds:[eax]004704AF BA EC044700 mov edx,dumped_.004704EC ; ASCII "Visual Assist X - Patch by BRD"004704B4 E8 7B6FFEFF call dumped_.00457434004704B9 8B0D 04F84700 mov ecx,dword ptr ds:[47F804] ; dumped_.00492DEC004704BF A1 14F74700 mov eax,dword ptr ds:[47F714]004704C4 8B00 mov eax,dword ptr ds:[eax]004704C6 8B15 10EA4600 mov edx,dword ptr ds:[46EA10] ; dumped_.0046EA5C004704CC E8 7B73FEFF call dumped_.0045784C ; CreateForm 004704D1 A1 14F74700 mov eax,dword ptr ds:[47F714]004704D6 8B00 mov eax,dword ptr ds:[eax]004704D8 E8 EF73FEFF call dumped_.004578CC ; Run004704DD E8 9E41F9FF call dumped_.00404680 ; Halt0

在 004704CC处有个 CreateForm,给后面的调试带来不小麻烦,没办法,屏幕小被遮住了!在 004704D8处 F7 至 004578CC

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

Page 5: Visual assist 10.8.2029.0 analysis

嗯,有点复杂,但是这是个 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...

Page 6: Visual assist 10.8.2029.0 analysis

** 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.dllERROR: 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的概览图:

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

Page 7: Visual assist 10.8.2029.0 analysis

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

0046F4FF 8B45 FC mov eax,dword ptr ss:[ebp-4] ; VS2010 处0046F502 8B80 2C030000 mov eax,dword ptr ds:[eax+32C]0046F508 8B80 20020000 mov eax,dword ptr ds:[eax+220]

0046F50E 33D2 xor edx,edx ; 清零0046F510 8B08 mov ecx,dword ptr ds:[eax]0046F512 FF51 38 call dword ptr ds:[ecx+38]0046F515 8B45 FC mov eax,dword ptr ss:[ebp-4]0046F518 8B80 2C030000 mov eax,dword ptr ds:[eax+32C]0046F51E 8B80 20020000 mov eax,dword ptr ds:[eax+220]0046F524 33D2 xor edx,edx0046F526 8B08 mov ecx,dword ptr ds:[eax]0046F528 FF51 38 call dword ptr ds:[ecx+38]0046F52B 8B45 FC mov eax,dword ptr ss:[ebp-4]0046F52E 8B80 2C030000 mov eax,dword ptr ds:[eax+32C]0046F534 8B80 20020000 mov eax,dword ptr ds:[eax+220]

0046F53A BA 74FB4600 mov edx,dumped_.0046FB74 ; 定位"** Locating VS 2010 installation **"0046F53F 8B08 mov ecx,dword ptr ds:[eax]0046F541 FF51 38 call dword ptr ds:[ecx+38]0046F544 8B45 FC mov eax,dword ptr ss:[ebp-4]0046F547 8B80 2C030000 mov eax,dword ptr ds:[eax+32C]

Page 8: Visual assist 10.8.2029.0 analysis

0046F54D 8B80 20020000 mov eax,dword ptr ds:[eax+220]

0046F553 BA A4FA4600 mov edx,dumped_.0046FAA4 ; 华丽的分割线0046F558 8B08 mov ecx,dword ptr ds:[eax]0046F55A FF51 38 call dword ptr ds:[ecx+38]0046F55D B2 01 mov dl,10046F55F A1 88E44600 mov eax,dword ptr ds:[46E488]0046F564 E8 1FF0FFFF call dumped_.0046E588 ; Registry::TRegistry::TRegistry(void)0046F569 8945 EC mov dword ptr ss:[ebp-14],eax0046F56C BA 01000080 mov edx,800000010046F571 8B45 EC mov eax,dword ptr ss:[ebp-14]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:[ebp-14]0046F583 E8 04F1FFFF call dumped_.0046E68C ; Registry::TRegistry::OpenKey(System::AnsiString,bool)0046F588 84C0 test al,al0046F58A 0F84 8A000000 je dumped_.0046F61A0046F590 8D4D E4 lea ecx,dword ptr ss:[ebp-1C]

0046F593 BA F0FB4600 mov edx,dumped_.0046FBF0 ; 获取注册表键值0046F598 8B45 EC mov eax,dword ptr ss:[ebp-14]0046F59B E8 B4F2FFFF call dumped_.0046E854 ; Registry::TRegistry::ReadString(System::AnsiString)0046F5A0 837D E4 00 cmp dword ptr ss:[ebp-1C],0 ; purge0046F5A4 74 74 je short dumped_.0046F61A0046F5A6 BA F0FB4600 mov edx,dumped_.0046FBF0 ; "44630d46-96b5-488c-8df926e21db8c1a3,10.8.2029.0"0046F5AB 8D4D F8 lea ecx,dword ptr ss:[ebp-8]0046F5AE 8B45 EC mov eax,dword ptr ss:[ebp-14] ; 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:[ebp-8]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:[ebp-4]0046F5C6 8B80 2C030000 mov eax,dword ptr ds:[eax+32C]0046F5CC 8B80 20020000 mov eax,dword ptr ds:[eax+220]0046F5D2 8B55 F8 mov edx,dword ptr ss:[ebp-8]0046F5D5 8B08 mov ecx,dword ptr ds:[eax]

Page 9: Visual assist 10.8.2029.0 analysis

0046F5D7 FF51 38 call dword ptr ds:[ecx+38]0046F5DA 8D4D F0 lea ecx,dword ptr ss:[ebp-10]0046F5DD 8B55 F4 mov edx,dword ptr ss:[ebp-C] ; "BINKY-PC"0046F5E0 8B45 F8 mov eax,dword ptr ss:[ebp-8] ; "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这个字符串,以为是注册码……我对 delphi不是很了解,就是百度了也找不到相关 API 函数的详细解释,所以在阅读

代码的时候遇到有关 delphi的 api 函数就见名知意吧,在 0046F5E3就是关键 call了,F7进去:

0046EF4C 55 push ebp0046EF4D 8BEC mov ebp,esp0046EF4F 81C4 9CFEFFFF add esp,-1640046EF55 53 push ebx0046EF56 56 push esi0046EF57 57 push edi0046EF58 33DB xor ebx,ebx0046EF5A 899D 9CFEFFFF mov dword ptr ss:[ebp-164],ebx0046EF60 895D F0 mov dword ptr ss:[ebp-10],ebx0046EF63 894D F4 mov dword ptr ss:[ebp-C],ecx0046EF66 8955 F8 mov dword ptr ss:[ebp-8],edx ; BINKY-PC0046EF69 8945 FC mov dword ptr ss:[ebp-4],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:[ebp-4]

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

0046EF7C 33C0 xor eax,eax ; 用完清零

Page 10: Visual assist 10.8.2029.0 analysis

0046EF7E 55 push ebp0046EF7F 68 9DF14600 push dumped_.0046F19D0046EF84 64:FF30 push dword ptr fs:[eax]0046EF87 64:8920 mov dword ptr fs:[eax],esp0046EF8A 33D2 xor edx,edx0046EF8C 55 push ebp0046EF8D 68 35F14600 push dumped_.0046F1350046EF92 64:FF32 push dword ptr fs:[edx]0046EF95 64:8922 mov dword ptr fs:[edx],esp0046EF98 8D55 EC lea edx,dword ptr ss:[ebp-14]0046EF9B 8B45 FC mov eax,dword ptr ss:[ebp-4]0046EF9E E8 39FEFFFF call dumped_.0046EDDC ; 0046EFA3 A1 14F74700 mov eax,dword ptr ds:[47F714]0046EFA8 8B00 mov eax,dword ptr ds:[eax]0046EFAA E8 7987FEFF call dumped_.00457728 ; Forms::TApplication::HandleMessage(void)0046EFAF 8B45 EC mov eax,dword ptr ss:[ebp-14]0046EFB2 33D2 xor edx,edx0046EFB4 52 push edx0046EFB5 50 push eax0046EFB6 8D95 9CFEFFFF lea edx,dword ptr ss:[ebp-164]0046EFBC B8 06000000 mov eax,60046EFC1 E8 8A9AF9FF call dumped_.00408A50 ; Sysutils::IntToHex(__int64,int)

0046EFC6 8B85 9CFEFFFF mov eax,dword ptr ss:[ebp-164] ; "CA398E13" ?0046EFCC BA B4F14600 mov edx,dumped_.0046F1B4 ; "FE4274C7" ?0046EFD1 E8 AE5BF9FF call dumped_.00404B84 ; System::__linkproc__ LStrCmp(void)0046EFD6 0F85 2D010000 jnz dumped_.0046F1090046EFDC 8D45 F0 lea eax,dword ptr ss:[ebp-10]0046EFDF B9 C8F14600 mov ecx,dumped_.0046F1C8 ; ASCII ".bak"0046EFE4 8B55 FC mov edx,dword ptr ss:[ebp-4]0046EFE7 E8 985AF9FF call dumped_.00404A84 ; System::__linkproc__ LStrCat3(void)0046EFEC 8B45 F0 mov eax,dword ptr ss:[ebp-10]

0046EFEF E8 389EF9FF call dumped_.00408E2C ; 判断文件是否存在 Sysutils::FileExists(System::AnsiString)0046EFF4 84C0 test al,al

0046EFF6 75 19 jnz short dumped_.0046F011 ; 为了看流程 zf=00046EFF8 6A 00 push 0 ; bFailIfExists0046EFFA 8B45 F0 mov eax,dword ptr ss:[ebp-10]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\

Page 11: Visual assist 10.8.2029.0 analysis

10.8.2029.0\VA_X.dll.bak"

0046F003 8B45 FC mov eax,dword ptr ss:[ebp-4] ; eax 存着".../VA_X.dll.bak",ss:[0012F5E8]中存着".../VA_X.dll"0046F006 E8 2D5CF9FF call dumped_.00404C380046F00B 50 push eax ; lpExistingFileName--".../VA_X.dll"

0046F00C E8 3378F9FF call <jmp.&kernel32.CopyFileA> ; CopyFileA 把原来的 VA_X.dll拷贝一份并改名 VA_X.dll.bak0046F011 8B55 FC mov edx,dword ptr ss:[ebp-4]0046F014 8D85 A0FEFFFF lea eax,dword ptr ss:[ebp-160]0046F01A E8 713FF9FF call dumped_.00402F90 ; System::__linkproc__ Assign(System::TTextRec &,System::AnsiString)0046F01F A1 94F74700 mov eax,dword ptr ds:[47F794]0046F024 C600 01 mov byte ptr ds:[eax],10046F027 BA 01000000 mov edx,10046F02C 8D85 A0FEFFFF lea eax,dword ptr ss:[ebp-160]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,1473C70046F041 8D85 A0FEFFFF lea eax,dword ptr ss:[ebp-160]

0046F047 E8 A443F9FF call dumped_.004033F0 ; 这里是寻找写入地址,和写入的整数个字符的数量 System::__linkproc__ Seek(System::TFileRec &,uint)0046F04C E8 A33BF9FF call dumped_.00402BF40046F051 6A 00 push 00046F053 BA 242B4700 mov edx,dumped_.00472B24 ; "l\n"0046F058 B9 07000000 mov ecx,70046F05D 8D85 A0FEFFFF lea eax,dword ptr ss:[ebp-160]

0046F063 E8 A040F9FF call dumped_.00403108 ; 这里开始写入 VA_X.dll System::__linkproc__ BlockWrite(System::TFileRec &,void *,int,int &)0046F068 E8 873BF9FF call dumped_.00402BF40046F06D BA 00201E00 mov edx,1E20000046F072 8D85 A0FEFFFF lea eax,dword ptr ss:[ebp-160]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 00046F084 BA 2C2B4700 mov edx,dumped_.00472B2C0046F089 B9 BA000000 mov ecx,0BA0046F08E 8D85 A0FEFFFF lea eax,dword ptr ss:[ebp-160]0046F094 E8 6F40F9FF call dumped_.00403108 ; System::__linkproc__ BlockWrite(System::TFileRec &,void *,int,int &)

Page 12: Visual assist 10.8.2029.0 analysis

0046F099 E8 563BF9FF call dumped_.00402BF4 ; System::__linkproc__ _IOTest(void)0046F09E 8D85 A0FEFFFF lea eax,dword ptr ss:[ebp-160]0046F0A4 E8 7F40F9FF call dumped_.00403128 ; System::__linkproc__ Close(System::TTextRec &)0046F0A9 E8 463BF9FF call dumped_.00402BF40046F0AE B2 01 mov dl,10046F0B0 A1 88E44600 mov eax,dword ptr ds:[46E488]0046F0B5 E8 CEF4FFFF call dumped_.0046E588 ; Registry::TRegistry::TRegistry(void)0046F0BA 8BD8 mov ebx,eax0046F0BC BA 01000080 mov edx,800000010046F0C1 8BC3 mov eax,ebx0046F0C3 E8 60F5FFFF call dumped_.0046E6280046F0C8 B1 01 mov cl,10046F0CA BA D8F14600 mov edx,dumped_.0046F1D8 ; ASCII "SOFTWARE\Whole Tomato\Visual Assist X"0046F0CF 8BC3 mov eax,ebx0046F0D1 E8 B6F5FFFF call dumped_.0046E68C ; Registry::TRegistry::OpenKey(System::AnsiString,bool)0046F0D6 84C0 test al,al0046F0D8 74 20 je short dumped_.0046F0FA0046F0DA 8B4D F8 mov ecx,dword ptr ss:[ebp-8] ; "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,ebx0046F0F5 E8 2EF7FFFF call dumped_.0046E828 ; Registry::TRegistry::WriteString(System::AnsiString,System::AnsiString)0046F0FA 8B45 F4 mov eax,dword ptr ss:[ebp-C]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_.0046F12B0046F109 837D EC 00 cmp dword ptr ss:[ebp-14],00046F10D 75 0F jnz short dumped_.0046F11E0046F10F 8B45 F4 mov eax,dword ptr ss:[ebp-C]0046F112 BA 98F24600 mov edx,dumped_.0046F298 ; ASCII "ERROR: File does not exist..."

Page 13: Visual assist 10.8.2029.0 analysis

0046F117 E8 B056F9FF call dumped_.004047CC0046F11C EB 0D jmp short dumped_.0046F12B0046F11E 8B45 F4 mov eax,dword ptr ss:[ebp-C]0046F121 BA C0F24600 mov edx,dumped_.0046F2C0 ; ASCII "ERROR: CRC missmatch. Wrong version?"0046F126 E8 A156F9FF call dumped_.004047CC0046F12B 33C0 xor eax,eax0046F12D 5A pop edx0046F12E 59 pop ecx0046F12F 59 pop ecx0046F130 64:8910 mov dword ptr fs:[eax],edx0046F133 EB 3A jmp short dumped_.0046F16F0046F135 ^ E9 924EF9FF jmp dumped_.00403FCC0046F13A 0200 add al,byte ptr ds:[eax]0046F13C 0000 add byte ptr ds:[eax],al0046F13E D878 40 fdivr dword ptr ds:[eax+40]0046F141 004E F1 add byte ptr ds:[esi-F],cl0046F144 46 inc esi0046F145 0000 add byte ptr ds:[eax],al0046F147 0000 add byte ptr ds:[eax],al0046F149 005D F1 add byte ptr ss:[ebp-F],bl0046F14C 46 inc esi0046F14D 008B 45F4BAF0 add byte ptr ds:[ebx+F0BAF445],c>0046F153 F2: prefix repne:0046F154 46 inc esi0046F155 00E8 add al,ch0046F157 71 56 jno short dumped_.0046F1AF0046F159 F9 stc

0046F15A FFEB jmp far ebx ; 非法使用寄存器0046F15C 0D 8B45F4BA or eax,BAF4458B0046F161 1C F3 sbb al,0F30046F163 46 inc esi0046F164 00E8 add al,ch0046F166 6256 F9 bound edx,qword ptr ds:[esi-7]

0046F169 FFE8 jmp far eax ; 非法使用寄存器0046F16B 99 cdq0046F16C 50 push eax0046F16D F9 stc0046F16E FF33 push dword ptr ds:[ebx]0046F170 C05A 59 59 rcr byte ptr ds:[edx+59],590046F174 64:8910 mov dword ptr fs:[eax],edx0046F177 68 A4F14600 push dumped_.0046F1A40046F17C 8D85 9CFEFFFF lea eax,dword ptr ss:[ebp-164]0046F182 E8 F155F9FF call dumped_.00404778 ; System::__linkproc__

Page 14: Visual assist 10.8.2029.0 analysis

LStrClr(void *)0046F187 8D45 F0 lea eax,dword ptr ss:[ebp-10]0046F18A E8 E955F9FF call dumped_.00404778 ; System::__linkproc__ LStrClr(void *)0046F18F 8D45 F8 lea eax,dword ptr ss:[ebp-8]0046F192 BA 02000000 mov edx,20046F197 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:[eax+4]004033F6 2D B1D70000 sub eax,0D7B1004033FB 83F8 02 cmp eax,2004033FE 77 19 ja short dumped_.0040341900403400 6A 00 push 0 ; dwMoveMethod00403402 8B41 08 mov eax,dword ptr ds:[ecx+8]00403405 F7E2 mul edx00403407 6A 00 push 0 ; lpDistanceToMoveHigh00403409 50 push eax ; lDistanceToMove0040340A FF31 push dword ptr ds:[ecx] ; hFile0040340C E8 2BDEFFFF call <jmp.&kernel32.SetFilePoi>

00403411 40 inc eax ; 返回+1字节偏移量00403412 ^ 0F84 0CF8FFFF je dumped_.00402C2400403418 C3 retn

他在调用了 SetFilePointer()时各参数的值:

0046f063-BlockWrite():00403108 55 push ebp00403109 8BEC mov ebp,esp0040310B 53 push ebx0040310C 8B5D 08 mov ebx,dword ptr ss:[ebp+8]0040310F 53 push ebx00403110 68 B2D70000 push 0D7B200403115 68 54304000 push <jmp.&kernel32.WriteFile>0040311A 6A 65 push 650040311C E8 3BFFFFFF call dumped_.0040305C

Page 15: Visual assist 10.8.2029.0 analysis

00403121 5B pop ebx00403122 5D pop ebp00403123 C2 0400 retn 4

Hook kernel32.WriteFile后,此处堆栈上个参数的值:

接着看 0046F078-Seek():004033F0 89C1 mov ecx,eax004033F2 0FB740 04 movzx eax,word ptr ds:[eax+4]004033F6 2D B1D70000 sub eax,0D7B1004033FB 83F8 02 cmp eax,2004033FE 77 19 ja short dumped_.0040341900403400 6A 00 push 000403402 8B41 08 mov eax,dword ptr ds:[ecx+8]00403405 F7E2 mul edx00403407 6A 00 push 000403409 50 push eax0040340A FF31 push dword ptr ds:[ecx]0040340C E8 2BDEFFFF call <jmp.&kernel32.SetFilePoin>00403411 40 inc eax 00403412 ^ 0F84 0CF8FFFF je dumped_.00402C2400403418 C3 retn

调用 SetFilePointer()时堆栈上变量的值:

0046F094-BlockWrite():00403108 55 push ebp00403109 8BEC mov ebp,esp0040310B 53 push ebx0040310C 8B5D 08 mov ebx,dword ptr ss:[ebp+8]0040310F 53 push ebx00403110 68 B2D70000 push 0D7B200403115 68 54304000 push <jmp.&kernel32.WriteFile>0040311A 6A 65 push 650040311C E8 3BFFFFFF call dumped_.0040305C00403121 5B pop ebx00403122 5D pop ebp00403123 C2 0400 retn 4

Hook kernel32.WriteFile后,此处堆栈上个参数的值:

Page 16: Visual assist 10.8.2029.0 analysis

一路走过来还算顺利,但是我对 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 00046F053 BA 242B4700 mov edx,dumped_.00472B24 ; "l\n"0046F058 B9 07000000 mov ecx,70046F05D 8D85 A0FEFFFF lea eax,dword ptr ss:[ebp-160]0046F063 E8 A040F9FF call dumped_.00403108 ; System::__linkproc__

BlockWrite(这里开始写入 VA_X.dll System::TFileRec &,void *,int,int &)0046F068 E8 873BF9FF call dumped_.00402BF4 ; RuntimeError0046F06D BA 00201E00 mov edx,1E20000046F072 8D85 A0FEFFFF lea eax,dword ptr ss:[ebp-160]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 00046F084 BA 2C2B4700 mov edx,dumped_.00472B2C0046F089 B9 BA000000 mov ecx,0BA0046F08E 8D85 A0FEFFFF lea eax,dword ptr ss:[ebp-160]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:[ebp-160]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:[ebp-8] ; "BINKY-PC"0046F0DD BA 08F24600 mov edx,dumped_.0046F208 ; ASCII "UserName"

Page 17: Visual assist 10.8.2029.0 analysis

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,ebx0046F0F5 E8 2EF7FFFF call dumped_.0046E828 ; Registry::TRegistry::WriteString(System::AnsiString,System::AnsiString)

我本来以为还要往注册表里写入所谓的"UserName"和"UserKey"呢,走完了,才发现,作者只是想开个玩笑--"You will never defeat the riddle of the Black Riders...",你永远无法解开黑暗骑士之谜,我了个……

说到这,那么问题就来了,因为小菜我想用 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]);

DescriptionF 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():

Page 18: Visual assist 10.8.2029.0 analysis

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

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

Page 19: Visual assist 10.8.2029.0 analysis

说明注册是分两步(两次 BlockWrite())来完成的,第一步去除主窗口,第二步完成注册!

第一次,调用WriteFile()的函数在 sub_0040305c,如下:0040305C 55 push ebp ; 调用writefile成功0040305D 8BEC mov ebp,esp0040305F 51 push ecx00403060 53 push ebx00403061 56 push esi00403062 57 push edi00403063 8BF1 mov esi,ecx

Page 20: Visual assist 10.8.2029.0 analysis

00403065 8BFA mov edi,edx00403067 8BD8 mov ebx,eax00403069 8B45 10 mov eax,dword ptr ss:[ebp+10]0040306C 0FB753 04 movzx edx,word ptr ds:[ebx+4]00403070 23D0 and edx,eax00403072 3BC2 cmp eax,edx00403074 75 58 jnz short dumped_.004030CE

00403076 6A 00 push 0 ; lpOverlapped=0, 不是以FILE_FLAG_OVERLAPPED方式打开00403078 8D45 FC lea eax,dword ptr ss:[ebp-4]0040307B 50 push eax ; lpNumberOfBytesWritten=0012F4380040307C 8B43 08 mov eax,dword ptr ds:[ebx+8]0040307F F7EE imul esi00403081 50 push eax ; nNumberOfBytesToWrite=700403082 57 push edi ; lpBuffer=00472B2400403083 8B03 mov eax,dword ptr ds:[ebx]00403085 50 push eax ; hFile=0000025c00403086 FF55 0C call dword ptr ss:[ebp+C] ; 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,esp0040305F 51 push ecx00403060 53 push ebx00403061 56 push esi00403062 57 push edi00403063 8BF1 mov esi,ecx00403065 8BFA mov edi,edx00403067 8BD8 mov ebx,eax00403069 8B45 10 mov eax,dword ptr ss:[ebp+10]0040306C 0FB753 04 movzx edx,word ptr ds:[ebx+4]00403070 23D0 and edx,eax00403072 3BC2 cmp eax,edx00403074 75 58 jnz short dumped_.004030CE

00403076 6A 00 push 0 ; lpOverlapped=0,不是以FILE_FLAG_OVERLAPPED方式打开00403078 8D45 FC lea eax,dword ptr ss:[ebp-4]0040307B 50 push eax ; lpNumberOfBytesWritten=0012F438

Page 21: Visual assist 10.8.2029.0 analysis

0040307C 8B43 08 mov eax,dword ptr ds:[ebx+8]0040307F F7EE imul esi00403081 50 push eax ; nNumberOfBytesToWrite=BA00403082 57 push edi ; lpBuffer=00472B2C00403083 8B03 mov eax,dword ptr ds:[ebx]00403085 50 push eax ; hFile=0000025c00403086 FF55 0C call dword ptr ss:[ebp+C] ; 00403054 (<jmp.&kernel32.WriteFile>)

00403089 85C0 test eax,eax ; eax=00000001 writefile调用成功0040308B 75 11 jnz short dumped_.0040309E

而写入的缓冲数据在 001E2000的 186byte:60 9C 8B 4C 24 24 81 39 4F 75 74 70 75 1A 81 7904 75 74 44 65 75 11 81 79 08 62 75 67 53 75 08C7 44 24 20 58 40 6D 1F 81 39 56 69 72 74 75 1A81 79 04 75 61 6C 50 75 11 81 79 08 72 6F 74 6575 08 C7 44 24 20 8B 40 6D 1F 9D 61 89 45 E4 837D E4 00 E9 74 93 F5 FF 8B 04 24 81 78 1E 33 5114 33 75 23 C7 45 EC C0 BA 30 66 C7 45 E4 34 5786 6C C7 45 E0 73 B8 88 F5 C7 45 DC CD 9D 2A E0C7 45 D8 13 BB 96 E8 33 C0 40 C3 C6 44 24 0C 4083 3D 00 10 D0 1E 00 74 1B C7 05 DF C2 D8 1E 33C0 40 E9 C7 05 E3 C2 D8 1E 39 06 00 00 C6 05 316A E0 1E 32 FF 25 34 42 6E 1F

只要在 winhex里找到 001473c7和 001E2000这两个地址,并替换成上述所给的数据,即可破解!