-
-
[原创]看雪CTF_2018 团队赛 第十题 write up
-
2018-12-20 01:07 4373
-
环境配置
系统 : Windows xp
程序 : enc0_crackme.rar
要求 : 输入口令
使用工具 : ida、od、c32asm、 peid、 DeDeDark
搜集线索
首先用peid查看信息,直接将cm拖入peid界面即可:
Borland Delphi 6.0 - 7.0 [Overlay]
提示这是一个delphi程序,我们使用dededark打开,弹出窗口的话直接下一步直到反编译操作完成。
我们查看唯一窗口的信息:
object frmcrackme: Tfrmcrackme Left = 176 Top = 218 BorderStyle = bsNone Caption = 'crackme' ClientHeight = 237 ClientWidth = 358 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] OldCreateOrder = False Position = poScreenCenter OnCreate = FormCreate OnShow = FormShow PixelsPerInch = 96 TextHeight = 13 object Splitter1: TSplitter Left = 0 Top = 33 Width = 5 Height = 114 end object Splitter2: TSplitter Left = 354 Top = 33 Width = 4 Height = 114 Align = alRight Color = clBtnShadow ParentColor = False end object Splitter3: TSplitter Left = 0 Top = 147 Width = 358 Height = 4 Cursor = crVSplit Align = alBottom Color = clBtnShadow ParentColor = False end object WebBrowser1: TWebBrowser Left = 5 Top = 33 Width = 349 Height = 114 TabStop = False Align = alClient PopupMenu = pm1 TabOrder = 0 ControlData = { 4C00000012240000C80B00000000000000000000000000000000000000000000 000000004C000000000000000000000001000000E0D057007335CF11AE690800 2B2E126208000000000000004C0000000114020000000000C000000000000046 8000000000000000000000000000000000000000000000000000000000000000 00000000000000000100000000000000000000000000000000000000} end object Panel1: TPanel Left = 0 Top = 0 Width = 358 Height = 33 Align = alTop BevelOuter = bvNone Caption = 'CrackMe' Color = clBtnShadow Ctl3D = False Font.Charset = ANSI_CHARSET Font.Color = clWhite Font.Height = -19 Font.Name = #23435#20307 Font.Style = [fsBold] ParentBackground = False ParentCtl3D = False ParentFont = False TabOrder = 1 OnMouseDown = Panel1MouseDown object Button1: TButton Left = 315 Top = -1 Width = 41 Height = 34 Hint = 'Exit' Caption = 'X' ParentShowHint = False ShowHint = True TabOrder = 0 OnClick = Button1Click end end object Panel2: TPanel Left = 0 Top = 151 Width = 358 Height = 86 Align = alBottom Caption = 'Panel2' TabOrder = 2 Visible = False object Memo1: TMemo Left = 1 Top = 1 Width = 356 Height = 84 Align = alClient Lines.Strings = ( 'Memo1') ScrollBars = ssBoth TabOrder = 0 end object Button2: TButton Left = 279 Top = 24 Width = 75 Height = 25 Caption = 'Button2' TabOrder = 1 OnClick = Button2Click end end object pm1: TPopupMenu Left = 112 Top = 24 object test1: TMenuItem Caption = 'test' end end object ApplicationEvents1: TApplicationEvents OnMessage = ApplicationEvents1Message Left = 176 Top = 56 end end
第一个Button1控件的提示(Hint)是Exit,也就是退出按钮。而第二个按钮Button2好似没有什么特殊信息,我们查看其单击响应函数的部分代码:
00469858 55 push ebp 00469859 8BEC mov ebp, esp 0046985B B96F000000 mov ecx, $0000006F 00469860 6A00 push $00 00469862 6A00 push $00 00469864 49 dec ecx 00469865 75F9 jnz 00469860 00469867 53 push ebx 00469868 56 push esi 00469869 57 push edi 0046986A 8BD8 mov ebx, eax 0046986C 8D75F4 lea esi, [ebp-$0C] 0046986F 33C0 xor eax, eax 00469871 55 push ebp 00469872 683A9B4600 push $00469B3A 00469877 64FF30 push dword ptr fs:[eax] 0046987A 648920 mov fs:[eax], esp 0046987D BAEC984600 mov edx, $004698EC 00469882 8955FC mov [ebp-$04], edx 00469885 BA01994600 mov edx, $00469901 0046988A 8955F8 mov [ebp-$08], edx 0046988D 8D95B0FCFFFF lea edx, [ebp+$FFFFFCB0] 00469893 8B06 mov eax, [esi] | 00469895 E80EF2F9FF call 00408AA8 0046989A 8B85B0FCFFFF mov eax, [ebp+$FFFFFCB0] * Reference to: Dialogs.ShowMessage(System.AnsiString) | 004698A0 E89B2EFCFF call 0042C740 004698A5 8D85ACFCFFFF lea eax, [ebp+$FFFFFCAC] 004698AB 50 push eax 004698AC 8B4DF8 mov ecx, [ebp-$08] 004698AF 8B55FC mov edx, [ebp-$04] 004698B2 A1C8CC4600 mov eax, dword ptr [$0046CCC8] | 004698B7 E880E1FFFF call 00467A3C 004698BC 8B95ACFCFFFF mov edx, [ebp+$FFFFFCAC] * Reference to control Tfrmcrackme.Memo1 : TMemo | 004698C2 8B8320030000 mov eax, [ebx+$0320] * Reference to: Controls.TControl.SetText(System.AnsiString) | 004698C8 E81B10FDFF call 0043A8E8 004698CD 8D4DEC lea ecx, [ebp-$14] * Possible String Reference to: 'crackme.exe' | 004698D0 BA509B4600 mov edx, $00469B50 004698D5 A1C8CC4600 mov eax, dword ptr [$0046CCC8] | 004698DA E8CDE2FFFF call 00467BAC 004698DF 90 nop 004698E0 90 nop 004698E1 9C pushf | 004698E2 E8E5E1FFFF call 00467ACC 004698E7 8C9692899247 mov word ptr [esi+$47928992], ss 004698ED 9B wait 004698EE 64B9FF17B5D1 mov ecx, $D1B517FF 004698F4 0300 add eax, [eax] 004698F6 14F6 adc al, $F6 004698F8 8C969289929A mov word ptr [esi+$9A928992], ss 004698FE 91 xchg eax, ecx 004698FF 9B wait
对于这个函数,可以重点观察下。
开始分析
我们将cm拖入ida,反编译工作完成,按下shift
+ F12
观察字符串:
CODE:00466E54 0000000B C disasm.dll CODE:00466E60 0000000A C od_disasm CODE:00466E6C 0000000C C od_assemble CODE:00468AE8 00000005 C none CODE:0046952C 00000009 C <script> CODE:00469560 00000005 C CTF CODE:0046957C 00000005 C 2018 CODE:004696CC 0000008F C <center><br><br><br><input value=\"\" id=\"pswd\" size=39></input><br><br><br><input type=button value=\"checkMyFlag\" onclick=\"ckpswd();\"></center> CODE:00469B7C 0000000B C disasm.dll
这里,由于字符串较少,仔细观察发现了可疑的字符串,004696CC 位置的字符串是脚本代码,而其部署的界面正好与程序界面相对应:
双击其交叉参考,查看更多信息:
CODE:00469598 unicode 0, <script language="vbscript"> CODE:00469598 dw 3Eh, 0Dh, 0Ah CODE:00469598 unicode 0, <function alert(msg_str)> CODE:00469598 dw 0Dh, 0Ah CODE:00469598 unicode 0, <MsgBox msg_str,vbOKOnly + vbExclamation + vbApplicationMo> CODE:00469598 unicode 0, <dal,""> CODE:00469598 dw 0Dh, 0Ah CODE:00469598 unicode 0, <End Function> CODE:00469598 dw 0Dh, 0Ah, 3Ch CODE:00469598 unicode 0, </script> CODE:00469598 dw 3Eh, 0 CODE:004696B8 dword_4696B8 dd 88000101h, 74697277h, 6E6C65h, 0FFFFFFFFh, 8Eh CODE:004696B8 ; DATA XREF: CODE:00469357o CODE:004696CC aCenterBrBrBrIn db '<center><br><br><br><input value="" id="pswd" size=39></input><br' CODE:004696CC ; DATA XREF: CODE:0046939Co CODE:004696CC db '><br><br><input type=button value="checkMyFlag" onclick="ckpswd()' CODE:004696CC db ';"></center>',0
所以有理由怀疑,Delphi程序载入了VBScript脚本来实现UI和其对应的响应函数。
我们直接用c32asm在文件中以ASCII和UNICODE形式搜索ckpswd
,发现没有什么直接的线索。
动态调试
在ida中已知引用脚本字符串的位置是:
CODE:00469349 mov edx, offset aScriptLanguage ; "<script language=\"vbscript\">\r\nfunct"... CODE:0046934E call j_@System@@WStrAsg$qqrr17System@WideStringx17System@WideString ; System::__linkproc__ WStrAsg(System::WideString &,System::WideString) CODE:00469353 lea eax, [ebp-0Ch] CODE:00469356 push eax CODE:00469357 push offset dword_4696B8 CODE:0046935C push offset dword_469518
我们对00469357下断,运行至469361,发现脚本字符串已经被压入栈中。此时,对其下内存访问断点,看看载入之后,会对其做什么操作:
下好之后直接按下F9
运行,发现断下来之后按下Alt
+K
查看调用栈:
调用堆栈: 主线程 地址 堆栈 函数过程 / 参数 调用来自 结构 0012E220 0040452F <jmp.&kernel32.MultiByteToWideChar> enc0_cra.0040452A 0012E21C 0012E224 00000003 CodePage = 3 0012E228 00000000 Options = 0 0012E22C 004696CC StringToMap = "<center><br><br><br><input value="" id="pswd" size=39></input><br><br><br><input type=button value="checkMyFlag" onclick="ckpswd();"></center>" 0012E230 0000008E StringSize = 8E (142.) 0012E234 0012E24C WideCharBuf = 0012E24C 0012E238 000007FF WideBufSize = 7FF (2047.) 0012E240 00404B8C enc0_cra.00404518 enc0_cra.00404B87 0012E23C 0012F25C 0040534F enc0_cra.00404B4C enc0_cra.0040534A 0012F268 0045C31C enc0_cra.00405334 enc0_cra.0045C317 0012F8E4 0045C71A ? enc0_cra.0045C214 enc0_cra.0045C715 0012FA00 0040FAD0 enc0_cra.0045C684 enc0_cra.0040FACA 0012F9FC 0012FA44 004693E3 enc0_cra.0040FA34 enc0_cra.004693DE 0012FA40
这是断在字符串转换的函数MultiByteToWideChar上了。我们删除内存断点,对新的Unicode字符串下断,然后继续F9
直到断在这行代码:
770F4B84 F3:A5 rep movs dword ptr es:[edi],dword ptr ds>
这是一段字符串拷贝的代码,此时查看调用栈:
调用堆栈: 主线程 地址 堆栈 函数过程 / 参数 调用来自 结构 0012E234 00404BE8 <jmp.&oleaut32.SysAllocStringLen> enc0_cra.00404BE3 0012E230 0012E244 00404B9F enc0_cra.00404BD8 enc0_cra.00404B9A 0012F25C 0040534F enc0_cra.00404B4C enc0_cra.0040534A 0012F268 0045C31C enc0_cra.00405334 enc0_cra.0045C317 0012F8E4 0045C71A ? enc0_cra.0045C214 enc0_cra.0045C715 0012FA00 0040FAD0 enc0_cra.0045C684 enc0_cra.0040FACA 0012F9FC 0012FA44 004693E3 enc0_cra.0040FA34 enc0_cra.004693DE 0012FA40
经过字符串的转换,不知道能不能发现关键信息呢,我们直接在内存中暴力搜索关键字"wrong":在内存面板右击->查找
->二进制字串
,在unicode一行输入wrong。按确定
进行查找,按下Ctrl
+l
查看下一个。
终于,发现了关键信息:
001D3960 77 00 72 00 6F 00 6E 00 67 00 21 00 3C 00 22 00 wrong!<" 001D3970 20 00 2B 00 20 00 61 00 20 00 2B 00 20 00 22 00 + a + " 001D3980 3E 00 20 00 69 00 73 00 20 00 6E 00 6F 00 74 00 > is not 001D3990 20 00 6D 00 79 00 20 00 47 00 55 00 49 00 44 00 my GUID 001D39A0 20 00 3B 00 2D 00 29 00 22 00 29 00 20 00 20 ;-)")
这就是程序弹出的错误信息,我们查看完整的脚本:
001D36C8 ?.function ckpswd() { > 001D3708 document.all.pswd.value; if 001D3748 (a == "kanxueCTF2018bySimpower91 001D3788 ") { alert("congratulatio 001D37C8 ns!") } else { alert(" 001D3808 wrong!<" + a + "> is not my GUID 001D3848 ;-)") }}.harCode(c+29):c.toS 001D3888 tring(36))};if(!''.replace(/^/,S 001D38C8 tring)){while(c--)d[e(c)]=k[c]|| 001D3908 e(c);k=[function(e){return d[e]} 001D3948 ];e=function(){return'\\w+'};c=1 001D3988 };while(c--)if(k[c])p=p.replace( 001D39C8 new RegExp('\\b'+e(c)+'\\b','g') 001D3A08 ,k[c]);return p}('$$$','8 4() { 001D3A48 1 = 6.3.e.f; 9 (1 == "b") 001D3A88 { 2("5!") } 7 { 001D3AC8 2("g!<" + 1 + "> a d c 0 ;-)") 001D3B08 }}',62,17,'GUID$$$@a$$$@alert 001D3B48 $$$@all$$$@ckpswd$$$@congratulat 001D3B88 ions$$$@document$$$@else$$$@func 001D3BC8 tion........£?..譠??...... >
根据硬编码信息,flag已经暴露无遗了。
夺旗成功
输入flag:kanxueCTF2018bySimpower91,程序提示congratulations!
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界