1、前言

公司大拿给写的一个CTF逆向程序,提升我们组内人员的水平。

  1. 基于对话框MFC框架开发,使用EDIT控制特性隐藏Flag,可借助spy4win之类窗体工具找出Flag
  2. 程序加UPX壳,已对壳信息混淆处理,PEiD无法识别出壳信息。
  3. DLL 依赖情况如图所示。

2、思路

程序用IDA查看的时候,因为有壳混淆后是没法跟下去的。这道题比较简单,破解还是常规思路。。。

  • 1)手动脱UPX壳
  • 2)IDA查找字符串,获取信息
  • 3)跟踪调用的函数

3、过程

1、脱壳

UPX是一款常用的压缩壳,单步跟踪法或者是ESP定律都能很快的脱掉它。

单步跟踪到如下反汇编指令处:


  1. 00406A10 pushad
  2. 00406A11 mov esi,ctf02.00406000
  3. 00406A16 lea edi,dword ptr ds:[esi-0x5000]
  4. 00406A1C push edi
  5. 00406A1D or ebp,-0x1
  6. 00406A20 jmp short ctf02.00406A32

F8单步向下运行,遇到向上的跳转就F4到下一条指令去,不让自己迷失在各种解密操作指令中。

  1. 00406A32 mov ebx,dword ptr ds:[esi]
  2. 00406A34 sub esi,-0x4
  3. 00406A37 adc ebx,ebx
  4. 00406A39 jb short ctf02.00406A28 ; 向上跳转,跳转实现向上运行
  5. 00406A3B mov eax,0x1 ; F4运行到此处,遇到红色跳转就下一条
  6. 00406A40 add ebx,ebx
  7. 00406A42 jnz short ctf02.00406A4B
  8. 00406A44 mov ebx,dword ptr ds:[esi]
  9. 00406A46 sub esi,-0x4
  10. 00406A49 adc ebx,ebx
  11. 00406A4B adc eax,eax
  12. 00406A4D add ebx,ebx
  13. 00406A4F jnb short ctf02.00406A40
  14. 00406A51 jnz short ctf02.00406A5C
  15. 00406A53 mov ebx,dword ptr ds:[esi]
  16. 00406A55 sub esi,-0x4
  17. 00406A58 adc ebx,ebx
  18. 00406A5A jnb short ctf02.00406A40
  19. 00406A5C xor ecx,ecx
  20. 00406A5E sub eax,0x3
  21. 00406A61 jb short ctf02.00406A70
  22. 00406A63 shl eax,0x8
  23. 00406A66 mov al,byte ptr ds:[esi]
  24. 00406A68 inc esi ; ctf02.0040600B
  25. 00406A69 xor eax,-0x1
  26. 00406A6C je short ctf02.00406AE2
  27. 00406A6E mov ebp,eax
  28. 00406A70 add ebx,ebx

接下来会遇见两个向上的跳转,一个小跳转,一个大跳转。

我们在NOP指令的下一行代码F4运行到那一条,接下来的操作就比较重复化,遇到跳转就F4到下一条。

然后遇到popad指令的时候说明我们距离OEP就不远了!

  1. 00406ABD mov al,byte ptr ds:[edx]
  2. 00406ABF inc edx ;
  3. 00406AC0 mov byte ptr ds:[edi],al
  4. 00406AC2 inc edi ;
  5. 00406AC3 dec ecx
  6. 00406AC4 jnz short ctf02.00406ABD ; 小跳转
  7. 00406AC6 jmp ctf02.00406A2E ; 大跳转
  8. 00406ACB nop
  9. 00406ACC mov eax,dword ptr ds:[edx] ; F4运行到此处
  10. 00406ACE add edx,0x4
  11. 00406AD1 mov dword ptr ds:[edi],eax
  12. 00406AD3 add edi,0x4
  13. 00406AD6 sub ecx,0x4
  14. 00406AD9 ja short ctf02.00406ACC ; 又是一个跳转的地方
  15. 00406ADB add edi,ecx ; F4运行到此处
  16. 00406ADD jmp ctf02.00406A2E ; 大跳转,F4运行到下一条语句
  17. 00406AE2 pop esi ;
  18. 00406AE3 mov edi,esi ; F4运行到此处
  19. 00406AE5 mov ecx,0x3B
  20. 00406AEA mov al,byte ptr ds:[edi]
  21. 00406AEC inc edi ;
  22. 00406AED sub al,0xE8
  23. 00406AEF cmp al,0x1
  24. 00406AF1 ja short ctf02.00406AEA ; 小跳转
  25. 00406AF3 cmp byte ptr ds:[edi],0x1 ; F4运行到此处
  26. 00406AF6 jnz short ctf02.00406AEA
  27. 00406AF8 mov eax,dword ptr ds:[edi] ; F4运行到此处
  28. 00406AFA mov bl,byte ptr ds:[edi+0x4]
  29. 00406AFD shr ax,0x8
  30. 00406B01 rol eax,0x10
  31. 00406B04 xchg ah,al
  32. 00406B06 sub eax,edi ;
  33. 00406B08 sub bl,0xE8
  34. 00406B0B add eax,esi ;
  35. 00406B0D mov dword ptr ds:[edi],eax
  36. 00406B0F add edi,0x5
  37. 00406B12 mov al,bl
  38. 00406B14 loopd short ctf02.00406AEF ; 循环操作
  39. 00406B16 lea edi,dword ptr ds:[esi+0x4000] ; F4运行到此处
  40. 00406B1C mov eax,dword ptr ds:[edi]
  41. 00406B1E or eax,eax
  42. 00406B20 je short ctf02.00406B67
  43. 00406B22 mov ebx,dword ptr ds:[edi+0x4]
  44. 00406B25>lea eax,dword ptr ds:[eax+esi+0x68BC]
  45. 00406B2C add ebx,esi ;
  46. 00406B2E push eax
  47. 00406B2F add edi,0x8
  48. 00406B32 call dword ptr ds:[esi+0x6920] ;
  49. 00406B38 xchg eax,ebp ;
  50. 00406B39 mov al,byte ptr ds:[edi]
  51. 00406B3B inc edi ;
  52. 00406B3C or al,al
  53. 00406B3E je short ctf02.00406B1C
  54. 00406B40 mov ecx,edi ;
  55. 00406B42 jns short ctf02.00406B4B
  56. 00406B44 movzx eax,word ptr ds:[edi]
  57. 00406B47 inc edi ;
  58. 00406B48 push eax
  59. 00406B49 inc edi ;
  60. 00406B4A db B9
  61. 00406B4B push edi ;
  62. 00406B4C dec eax
  63. 00406B4D repne scas byte ptr es:[edi]
  64. 00406B4F push ebp ;
  65. 00406B50 call dword ptr ds:[esi+0x6924] ;
  66. 00406B56 or eax,eax
  67. 00406B58 je short ctf02.00406B61
  68. 00406B5A mov dword ptr ds:[ebx],eax
  69. 00406B5C add ebx,0x4
  70. 00406B5F jmp short ctf02.00406B39 ; 无条件跳转
  71. 00406B61 call dword ptr ds:[esi+0x6934] ;
  72. 00406B67 mov ebp,dword ptr ds:[esi+0x6928] ; F4运行到此处
  73. 00406B6D lea edi,dword ptr ds:[esi-0x1000]
  74. 00406B73 mov ebx,0x1000
  75. 00406B78 push eax
  76. 00406B79 push esp
  77. 00406B7A push 0x4
  78. 00406B7C push ebx
  79. 00406B7D push edi ;
  80. 00406B7E call ebp ;
  81. 00406B80 lea eax,dword ptr ds:[edi+0x207]
  82. 00406B86 and byte ptr ds:[eax],0x7F
  83. 00406B89 and byte ptr ds:[eax+0x28],0x7F
  84. 00406B8D pop eax
  85. 00406B8E push eax
  86. 00406B8F push esp
  87. 00406B90 push eax
  88. 00406B91 push ebx
  89. 00406B92 push edi ;
  90. 00406B93 call ebp ;
  91. 00406B95 pop eax
  92. 00406B96 popad ; 到这里的时候说明快到OEP
  93. 00406B97 lea eax,dword ptr ss:[esp-0x80]
  94. 00406B9B push 0x0
  95. 00406B9D cmp esp,eax
  96. 00406B9F jnz short ctf02.00406B9B
  97. 00406BA1 sub esp,-0x80
  98. 00406BA4 jmp ctf02.00401750 ; 跳转到OEP

到了00406BA4 这里的时候,我用OD插件-Ollydump脱壳。

2、IDA查看

脱了壳后的程序,用IDA看就没有障碍了。

IDA打开后-View - Open Subviews - Srings

然后X键,查看哪个函数在引用它,F5查看C源码就确认出Flag了。

  1. signed int __thiscall sub_4012B0(CDialog *this)
  2. {
  3. CDialog *v1; // esi@1
  4. HMENU v2; // eax@1
  5. struct CMenu *v3; // edi@1
  6. LPCSTR lpNewItem; // [sp+8h] [bp-10h]@2
  7. int v6; // [sp+14h] [bp-4h]@2
  8. v1 = this;
  9. CDialog::OnInitDialog(this);
  10. v2 = GetSystemMenu(*((HWND *)v1 + 8), 0);
  11. v3 = CMenu::FromHandle(v2);
  12. if ( v3 )
  13. {
  14. CString::CString(&lpNewItem);
  15. v6 = 0;
  16. CString::LoadStringA((CString *)&lpNewItem, 0x65u);
  17. if ( *((_DWORD *)lpNewItem - 2) )
  18. {
  19. AppendMenuA(*((HMENU *)v3 + 1), 0x800u, 0, 0);
  20. AppendMenuA(*((HMENU *)v3 + 1), 0, 0x10u, lpNewItem);
  21. }
  22. v6 = -1;
  23. CString::~CString((CString *)&lpNewItem);
  24. }
  25. SendMessageA(*((HWND *)v1 + 8), 0x80u, 1u, *((_DWORD *)v1 + 40));
  26. SendMessageA(*((HWND *)v1 + 8), 0x80u, 0, *((_DWORD *)v1 + 40)); //发送消息到窗口
  27. CWnd::SetWindowTextA((CDialog *)((char *)v1 + 96), "6C9F69EF-C170-4e43-A007-9AA3526823DB"); //设置文本
  28. SendMessageA(*((HWND *)v1 + 32), 0xCCu, 0x2Eu, 0);
  29. return 1;
  30. }

4、附件下载地址

https://github.com/zprogram/zprogram.github.io/blob/master/Blog_attachment/CTF/CTF_REVERSE_ctf02_查找字符串.zip

5、参考

手脱UPX壳的几种方法

http://blog.csdn.net/xiaoyuai1234/article/details/51463501

【CTF REVERSE】ctf02-查找字符串的更多相关文章

  1. 在文件夹中 的指定类型文件中 查找字符串(CodeBlocks+GCC编译,控制台程序,仅能在Windows上运行)

    说明: 程序使用 io.h 中的 _findfirst 和 _findnext 函数遍历文件夹,故而程序只能在 Windows 下使用. 程序遍历当前文件夹,对其中的文件夹执行递归遍历.同时检查遍历到 ...

  2. php查找字符串首次出现的位置 判断字符串是否在另一个字符串中

    strpos - 查找字符串首次出现的位置 说明 int strpos ( string $haystack , mixed $needle [, int $offset = 0 ] ) 返回 nee ...

  3. 查找字符串的 KMP 算法

    查找字符串是我们平常编程过程中经常遇到的,现在介绍一种查找字符串算法,增加程序的执行速度. 通常我们是这么写的: /* content: search a string in a othor stri ...

  4. 回朔法/KMP算法-查找字符串

    回朔法:在字符串查找的时候最容易想到的是暴力查找,也就是回朔法.其思路是将要寻找的串的每个字符取出,然后按顺序在源串中查找,如果找到则返回true,否则源串索引向后移动一位,再重复查找,直到找到返回t ...

  5. Lua查找字符串注意

    问题: 使用Lua写Wireshark插件时,经常匹配字符串.今天使用string.find()函数查找字符串”max-age”,没有找到. 分析: local index = string.find ...

  6. Javascript 查找字符串中出现最多的字符和出现的次数

    <script type="text/javascript"> //查找字符串中出现最多的字符和出现的次数 var str = 'Thatwheneying its o ...

  7. 查找字符串(C++实现)

    查找字符串(C++实现),不使用库函数: // SubString.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include < ...

  8. php查找字符串是否存在

    strstr //搜索字符串在另一字符串中的首次出现(对大小写敏感) //该函数返回字符串的其余部分(从匹配点).如未找到则返回 false stristr //查找字符串在另一字符串中第一次出现的位 ...

  9. linux上查找文件存放地点和文件中查找字符串方法

    一.查找文件存放地点 1.locate 语法:locate <filename> locate命令实际是"find -name"的另一种写法,但是查找方式跟find不同 ...

随机推荐

  1. 【Luogu5108】仰望半月的夜空(后缀数组)

    [Luogu5108]仰望半月的夜空(后缀数组) 题面 洛谷 题解 实名举报这题在比赛之前还不是这个样子的,还被我用SAM给水过去了 很明显求出\(SA\)之后就是按照\(SA\)的顺序从前往后考虑每 ...

  2. KEIL中函数定义存在但go to definition却不跳转的原因

    可能是 go to definition 函数的地方,被包含在一个未使能的条件编译宏内部,因为这样KEIL在编译时,就未将该条件编译宏内部的信息编译入工程的Browse Information.

  3. 洛谷P1600 天天爱跑步

    天天放毒... 首先介绍一个树上差分. 每次进入的时候记录贡献,跟出来的时候的差值就是子树贡献. 然后就可以做了. 发现考虑每个人的贡献有困难. 于是考虑每个观察员的答案. 把路径拆成两条,以lca分 ...

  4. typescript枚举,类型推论,类型兼容性,高级类型,Symbols(学习笔记非干货)

    枚举部分 Enumeration part 使用枚举我们可以定义一些有名字的数字常量. 枚举通过 enum关键字来定义. Using enumerations, we can define some ...

  5. js中if()条件中变量为false的情况

    <html> <head> <script type="text/javascript" src="jquery-3.1.1.min.js& ...

  6. Boost filessystem...

    CMakeList.txt: cmake_minimum_required(VERSION 3.8) project(Demo) ) set(SOURCE_FILES main.cpp) //需要添加 ...

  7. 如何解决win7系统无法运行cmd命令提示符

    如何解决win7系统无法运行cmd命令提示符   CMD命令可以帮助我们很快的执行所需要的程序命令,可以查询系统中很多的信息和解决系统很多的故障,对我们来说非常方便,但是最近有用户反馈自己win7电脑 ...

  8. javascript 事件冒泡与取消冒泡

    事件冒泡: 当一个元素上的事件被触发时,比如说鼠标点击了一个按钮,同样的事件将会在那个元素的所有祖先中被触发,这一过程被称为事件冒泡. 这个事件从原始祖先开始,一直冒泡到DOM树的最上层.(bug) ...

  9. Spark记录-spark-env.sh配置

    环境变量 含义 SPARK_MASTER_IP master实例绑定的IP地址,例如,绑定到一个公网IP SPARK_MASTER_PORT mater实例绑定的端口(默认7077) SPARK_MA ...

  10. Tomcat 或JBOSS java.lang.ArrayIndexOutOfBoundsException: 8192 解决方案【转】

    错误信息: 2017-1-17 10:09:39 org.apache.catalina.core.StandardWrapperValve invoke 严重: Servlet.service() ...