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
楼主牛逼,赞一个 分析的很透彻, 多谢分享。 之前一直用Trial-Reset来免除限制,但是30天一次太麻烦了,感谢啊,精华!!! 膜拜大神,先学习了 很好很强大 快乐海岸线 发表于 2015-2-1 15:51
楼主分析的好透彻啊 赞一个
你也是今天注册的{:301_997:}
你能看到图吗?我用的是长城宽带,验证码什么都不显示,然后开了vpn重新获取验证码,然后图就不见 后面的代码怎么都被合并到一起了,从word里直接粘的?你可以试下这个功能,帖子编辑好可以获得精华鼓励!
重新编好了,终于有图了,话说的宽带问题太麻烦了,不挂vpn就没有验证码,挂了vpn重新编辑这张帖子都卡的{:301_995:} Terrorblade 发表于 2015-2-1 19:58
重新编好了,终于有图了,话说的宽带问题太麻烦了,不挂vpn就没有验证码,挂了vpn重新编辑这张帖子都卡的{: ...
赞,咋弄了2个贴?直接覆盖在主贴上不好? Hmily 发表于 2015-2-1 21:04
赞,咋弄了2个贴?直接覆盖在主贴上不好?
不好意思H大,因为在看雪那边好像没有重新编辑的功能,而且在52pojie编辑的帖子真的有点困难,我今天折腾一个了1个小时才注册成功,因为我的长城宽带确实看不到验证码{:301_972:}……我本来以为重新发出来您就把原来的楼移走,我不知道编辑功能在哪呀,另外我是个dota玩家,最近dota亚洲杯,我一编辑又去看比赛了{:301_1008:} Terrorblade 发表于 2015-2-1 21:41
不好意思H大,因为在看雪那边好像没有重新编辑的功能,而且在52pojie编辑的帖子真的有点困难,我今天折腾 ...
牛逼。。。还是dota牛啊!你直接把编辑好的帖子,点击源代码,然后复制到主题贴那个源代码你就可以了。 楼主分析的好透彻啊 赞一个 Terrorblade 发表于 2015-2-1 21:41
不好意思H大,因为在看雪那边好像没有重新编辑的功能,而且在52pojie编辑的帖子真的有点困难,我今天折腾 ...
辛苦了,还有最后一个问题就完美了, 那些图片直接复制不行,必须上传然后指定到原帖处,不然一会就失效了。 Hmily 发表于 2015-2-2 11:27
辛苦了,还有最后一个问题就完美了, 那些图片直接复制不行,必须上传然后指定到原帖处,不然一会就失效 ...
谢谢H大提醒,小菜我在用word复制的时候就看到图片是复制不了的,后来买了个稳定vpn上传了图片,应该不会失效{:301_977:}