这道题是XCTF攻防世界上的一道新手入门题目!

年前刚接触逆向时IDA,OD了这些工具都不会用(负基础),当时做这些题的时候觉得挺难(主要是缺少练习,没思路无从下手)。现在回头再来看这些题目感觉确实是入门级的题目,所以逆向是门艺术更是门技术,需要多练习熟悉工具和掌握一些技巧,下面就来分析一下这道题目。

题目给了一个附件是一个exe的可执行文件,那好我们先来执行一下他好了!

结果出来一大堆英文,奈何本人英文真的很菜,高考40分:),浑身发憷,不怕手机自带拍照翻译,虽然翻译的水平很一般但是磕磕绊绊的还是能明白他什么意思:

这是个游戏(游戏规则:把那几个图形都看成灯,当其都亮时,也就是图形变成实心的游戏胜利),你必须把这个游戏过了之后才会得到我们想要的flag。 我们是要通过工具来获得这个flag,当然如果你玩游戏很nb的话你也可以通关他获得flag。

好废话不多说我们现在就来寻找flag!

1. 我们先用PEID分析一下程序的基本信息

可以看到检测到其未压缩,说明此程序无壳。下面我们可以选择用静态分析工具IDA来分析程序,也可以选用动态调试工具Ollydbg。

我们先用IDA来分析吧,因为此程序为32位的所以我们用32位的IDA打开程序。

  1. 我们按Ctrl + E弹出入口函数的信息,点击确定进入入口函数。因为此程序是一个控制台程序,所以我们需要找到main函数(处理逻辑在main函数里)。

进入start函数后我们就可以利用IDA一个强大插件的功能:把反汇编指令转化为C语言式的伪代码,这样我们方便寻找main函数。一般经过IDA的处理后都会显示出main函数的函数名,这种情况我们就可以直接通过寻找main函数名来寻找main函数。

但是有的程序在编译时,进行一些设置后IDA无法显示出main函数的函数名,这时我们就不能直接通过查找main函数名来寻找main函数,我们需要通过代码特征进行定位main函数,因为main()结束后会调用exit()函数来退出进程,所以我们只要找到exit函数,那么在其上方的函数就是main函数(也有可能是在这个上方函数的函数才是main函数)。


这个程序我们找到了exit函数,其上方有个invoke_main()函数,那么此函数应该为main函数(或者main函数在其内部),双击此函数进入函数内部。果然main函数在此函数内部,我们在双击进入main函数最里层,查看main函数的逻辑代码。我们对main函数中的逻辑代码进行分析看flag是怎么产生的。往下查看代码发现一处判断,正好像是判断那几盏灯是否都亮的逻辑,当这几盏灯都亮(也就是其值都为1)时,调用Sub_457Ab4( )函数,此函数应该就是flag产生的代码。

我们双击进入sub_457AB4()其处理代码为:

  1. int sub_45E940()
  2. {
  3. signed int i; // [esp+D0h] [ebp-94h]
  4. char v2; // [esp+DCh] [ebp-88h]
  5. char v3; // [esp+DDh] [ebp-87h]
  6. char v4; // [esp+DEh] [ebp-86h]
  7. char v5; // [esp+DFh] [ebp-85h]
  8. char v6; // [esp+E0h] [ebp-84h]
  9. char v7; // [esp+E1h] [ebp-83h]
  10. char v8; // [esp+E2h] [ebp-82h]
  11. char v9; // [esp+E3h] [ebp-81h]
  12. char v10; // [esp+E4h] [ebp-80h]
  13. char v11; // [esp+E5h] [ebp-7Fh]
  14. char v12; // [esp+E6h] [ebp-7Eh]
  15. char v13; // [esp+E7h] [ebp-7Dh]
  16. char v14; // [esp+E8h] [ebp-7Ch]
  17. char v15; // [esp+E9h] [ebp-7Bh]
  18. char v16; // [esp+EAh] [ebp-7Ah]
  19. char v17; // [esp+EBh] [ebp-79h]
  20. char v18; // [esp+ECh] [ebp-78h]
  21. char v19; // [esp+EDh] [ebp-77h]
  22. char v20; // [esp+EEh] [ebp-76h]
  23. char v21; // [esp+EFh] [ebp-75h]
  24. char v22; // [esp+F0h] [ebp-74h]
  25. char v23; // [esp+F1h] [ebp-73h]
  26. char v24; // [esp+F2h] [ebp-72h]
  27. char v25; // [esp+F3h] [ebp-71h]
  28. char v26; // [esp+F4h] [ebp-70h]
  29. char v27; // [esp+F5h] [ebp-6Fh]
  30. char v28; // [esp+F6h] [ebp-6Eh]
  31. char v29; // [esp+F7h] [ebp-6Dh]
  32. char v30; // [esp+F8h] [ebp-6Ch]
  33. char v31; // [esp+F9h] [ebp-6Bh]
  34. char v32; // [esp+FAh] [ebp-6Ah]
  35. char v33; // [esp+FBh] [ebp-69h]
  36. char v34; // [esp+FCh] [ebp-68h]
  37. char v35; // [esp+FDh] [ebp-67h]
  38. char v36; // [esp+FEh] [ebp-66h]
  39. char v37; // [esp+FFh] [ebp-65h]
  40. char v38; // [esp+100h] [ebp-64h]
  41. char v39; // [esp+101h] [ebp-63h]
  42. char v40; // [esp+102h] [ebp-62h]
  43. char v41; // [esp+103h] [ebp-61h]
  44. char v42; // [esp+104h] [ebp-60h]
  45. char v43; // [esp+105h] [ebp-5Fh]
  46. char v44; // [esp+106h] [ebp-5Eh]
  47. char v45; // [esp+107h] [ebp-5Dh]
  48. char v46; // [esp+108h] [ebp-5Ch]
  49. char v47; // [esp+109h] [ebp-5Bh]
  50. char v48; // [esp+10Ah] [ebp-5Ah]
  51. char v49; // [esp+10Bh] [ebp-59h]
  52. char v50; // [esp+10Ch] [ebp-58h]
  53. char v51; // [esp+10Dh] [ebp-57h]
  54. char v52; // [esp+10Eh] [ebp-56h]
  55. char v53; // [esp+10Fh] [ebp-55h]
  56. char v54; // [esp+110h] [ebp-54h]
  57. char v55; // [esp+111h] [ebp-53h]
  58. char v56; // [esp+112h] [ebp-52h]
  59. char v57; // [esp+113h] [ebp-51h]
  60. char v58; // [esp+114h] [ebp-50h]
  61. char v59; // [esp+120h] [ebp-44h]
  62. char v60; // [esp+121h] [ebp-43h]
  63. char v61; // [esp+122h] [ebp-42h]
  64. char v62; // [esp+123h] [ebp-41h]
  65. char v63; // [esp+124h] [ebp-40h]
  66. char v64; // [esp+125h] [ebp-3Fh]
  67. char v65; // [esp+126h] [ebp-3Eh]
  68. char v66; // [esp+127h] [ebp-3Dh]
  69. char v67; // [esp+128h] [ebp-3Ch]
  70. char v68; // [esp+129h] [ebp-3Bh]
  71. char v69; // [esp+12Ah] [ebp-3Ah]
  72. char v70; // [esp+12Bh] [ebp-39h]
  73. char v71; // [esp+12Ch] [ebp-38h]
  74. char v72; // [esp+12Dh] [ebp-37h]
  75. char v73; // [esp+12Eh] [ebp-36h]
  76. char v74; // [esp+12Fh] [ebp-35h]
  77. char v75; // [esp+130h] [ebp-34h]
  78. char v76; // [esp+131h] [ebp-33h]
  79. char v77; // [esp+132h] [ebp-32h]
  80. char v78; // [esp+133h] [ebp-31h]
  81. char v79; // [esp+134h] [ebp-30h]
  82. char v80; // [esp+135h] [ebp-2Fh]
  83. char v81; // [esp+136h] [ebp-2Eh]
  84. char v82; // [esp+137h] [ebp-2Dh]
  85. char v83; // [esp+138h] [ebp-2Ch]
  86. char v84; // [esp+139h] [ebp-2Bh]
  87. char v85; // [esp+13Ah] [ebp-2Ah]
  88. char v86; // [esp+13Bh] [ebp-29h]
  89. char v87; // [esp+13Ch] [ebp-28h]
  90. char v88; // [esp+13Dh] [ebp-27h]
  91. char v89; // [esp+13Eh] [ebp-26h]
  92. char v90; // [esp+13Fh] [ebp-25h]
  93. char v91; // [esp+140h] [ebp-24h]
  94. char v92; // [esp+141h] [ebp-23h]
  95. char v93; // [esp+142h] [ebp-22h]
  96. char v94; // [esp+143h] [ebp-21h]
  97. char v95; // [esp+144h] [ebp-20h]
  98. char v96; // [esp+145h] [ebp-1Fh]
  99. char v97; // [esp+146h] [ebp-1Eh]
  100. char v98; // [esp+147h] [ebp-1Dh]
  101. char v99; // [esp+148h] [ebp-1Ch]
  102. char v100; // [esp+149h] [ebp-1Bh]
  103. char v101; // [esp+14Ah] [ebp-1Ah]
  104. char v102; // [esp+14Bh] [ebp-19h]
  105. char v103; // [esp+14Ch] [ebp-18h]
  106. char v104; // [esp+14Dh] [ebp-17h]
  107. char v105; // [esp+14Eh] [ebp-16h]
  108. char v106; // [esp+14Fh] [ebp-15h]
  109. char v107; // [esp+150h] [ebp-14h]
  110. char v108; // [esp+151h] [ebp-13h]
  111. char v109; // [esp+152h] [ebp-12h]
  112. char v110; // [esp+153h] [ebp-11h]
  113. char v111; // [esp+154h] [ebp-10h]
  114. char v112; // [esp+155h] [ebp-Fh]
  115. char v113; // [esp+156h] [ebp-Eh]
  116. char v114; // [esp+157h] [ebp-Dh]
  117. char v115; // [esp+158h] [ebp-Ch]
  118. sub_45A7BE("done!!! the flag is ");
  119. v59 = 18;
  120. v60 = 64;
  121. v61 = 98;
  122. v62 = 5;
  123. v63 = 2;
  124. v64 = 4;
  125. v65 = 6;
  126. v66 = 3;
  127. v67 = 6;
  128. v68 = 48;
  129. v69 = 49;
  130. v70 = 65;
  131. v71 = 32;
  132. v72 = 12;
  133. v73 = 48;
  134. v74 = 65;
  135. v75 = 31;
  136. v76 = 78;
  137. v77 = 62;
  138. v78 = 32;
  139. v79 = 49;
  140. v80 = 32;
  141. v81 = 1;
  142. v82 = 57;
  143. v83 = 96;
  144. v84 = 3;
  145. v85 = 21;
  146. v86 = 9;
  147. v87 = 4;
  148. v88 = 62;
  149. v89 = 3;
  150. v90 = 5;
  151. v91 = 4;
  152. v92 = 1;
  153. v93 = 2;
  154. v94 = 3;
  155. v95 = 44;
  156. v96 = 65;
  157. v97 = 78;
  158. v98 = 32;
  159. v99 = 16;
  160. v100 = 97;
  161. v101 = 54;
  162. v102 = 16;
  163. v103 = 44;
  164. v104 = 52;
  165. v105 = 32;
  166. v106 = 64;
  167. v107 = 89;
  168. v108 = 45;
  169. v109 = 32;
  170. v110 = 65;
  171. v111 = 15;
  172. v112 = 34;
  173. v113 = 18;
  174. v114 = 16;
  175. v115 = 0;
  176. v2 = 123;
  177. v3 = 32;
  178. v4 = 18;
  179. v5 = 98;
  180. v6 = 119;
  181. v7 = 108;
  182. v8 = 65;
  183. v9 = 41;
  184. v10 = 124;
  185. v11 = 80;
  186. v12 = 125;
  187. v13 = 38;
  188. v14 = 124;
  189. v15 = 111;
  190. v16 = 74;
  191. v17 = 49;
  192. v18 = 83;
  193. v19 = 108;
  194. v20 = 94;
  195. v21 = 108;
  196. v22 = 84;
  197. v23 = 6;
  198. v24 = 96;
  199. v25 = 83;
  200. v26 = 44;
  201. v27 = 121;
  202. v28 = 104;
  203. v29 = 110;
  204. v30 = 32;
  205. v31 = 95;
  206. v32 = 117;
  207. v33 = 101;
  208. v34 = 99;
  209. v35 = 123;
  210. v36 = 127;
  211. v37 = 119;
  212. v38 = 96;
  213. v39 = 48;
  214. v40 = 107;
  215. v41 = 71;
  216. v42 = 92;
  217. v43 = 29;
  218. v44 = 81;
  219. v45 = 107;
  220. v46 = 90;
  221. v47 = 85;
  222. v48 = 64;
  223. v49 = 12;
  224. v50 = 43;
  225. v51 = 76;
  226. v52 = 86;
  227. v53 = 13;
  228. v54 = 114;
  229. v55 = 1;
  230. v56 = 117;
  231. v57 = 126;
  232. v58 = 0;
  233. for ( i = 0; i < 56; ++i )
  234. {
  235. *(&v2 + i) ^= *(&v59 + i);
  236. *(&v2 + i) ^= 0x13u;
  237. }
  238. return sub_45A7BE("%s\n");
  239. }

其是将V2 - V57与 V59 - V114的字符分别异或之后再与0x13u异或后,得到的字符串就为flag

注意此代码不能直接复制粘贴到进行使用,因为其默认V2 - V115的变量是连续存储的(即地址是连续的),而实际其会因为字节对齐而不连续存储,所以要自己写代码的到flag。

下面是我用c++写的代码(python语法都忘光了!)。

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. char a[] = {123, 32, 18, 98, 119, 108, 65, 41, 124,80,125,38, 124,111,74, 49, 83, 108,94,
  6. 108, 84, 6, 96, 83, 44, 121,104,110,32,95, 117,101, 99,123,127,119,96, 48,
  7. 107, 71, 92, 29, 81, 107, 90, 85, 64, 12,43, 76, 86, 13, 114,1, 117,126,0,
  8. 18, 64, 98, 5, 2, 4, 6, 3, 6, 48,49, 65, 32, 12, 48, 65, 31, 78, 62,
  9. 32, 49, 32, 1, 57, 96, 3, 21, 9, 4, 62, 3, 5, 4, 1, 2, 3, 44, 65,
  10. 78, 32, 16, 97, 54, 16, 44, 52, 32, 64,89, 45, 32, 65, 15, 34, 18, 16, 0 };
  11. cout<<"done!!! the flag is: ";
  12. for (int i = 0; i < 56; ++i )
  13. {
  14. a[i] = a[i] ^ a[i+57];
  15. a[i] = a[i] ^ 0x13u;
  16. cout<<a[i];
  17. }
  18. return 0;
  19. }

flag为zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t}

下面我们用Ollydbg来分析这道题:

打开OD运行这个程序,其会停在入口处,然后我们点击鼠标右键-》中文搜索引擎-》智能搜索。会弹出所有字符串的信息!我们会发现this is a flag:字符串(说明字符串是在此处产生的),我们双击此字符串进入此代码块。

进入代码块后我们往下查看代码,我们发现%s/n字符串作为参数传给一个函数,所以此函数应该为printf函数,eax为显示字符串的指针。(此字符串就是flag)

上方代码应为flag的处理代码。

我们要获得flag就必须执行这块代码,所以我们在其flag的处理代码块的第一条指令处右击鼠标-》点击设置为新eip,在printf函数的入口参数处下断点,然后运行程序。

当程序到达断点处是会停止运行,因为断点处为printf函数处,而eax为所显示flag字符串的指针所以我们在OD右上角的寄存器窗口中可以看到flag。

一个入门级CTF的Reverse的更多相关文章

  1. Daily,一个入门级的 React Native 应用

    Daily,一个React-Native写的android app. 下拉刷新获取:图片.诗句.言语.音乐.乐评.雨声.知乎日报.历史上的今天. 可以说是一个入门级的React-Native应用. 项 ...

  2. 如何实现shell并发 一个入门级可控多线程shell脚本方案

     如何实现shell并发      很多人都问我如何写shell脚本,如何实现同时给三台ftp服务器上传文件,如何同时检测三台服务器是否alive等,其实这就是想实现shell的并发.那么shell并 ...

  3. 写一个小CTF平台

    0x00.前言 协会要举办信息安全大赛了,初赛的web+crypto+misc主要由我来出题,注册.比赛的平台也都要由我来写    上周日完成了注册页面的后端(前端由另一个女生写的),前天下午大概完成 ...

  4. 如何开始你的CTF比赛之旅-网站安全-

    在过去的两个星期里,我已经在DEFCON 22 CTF里检测出了两个不同的问题:“shitsco ”和“ nonameyet ”.感谢所有 的意见和评论,我遇到的最常见的问题是:“我怎么才能在CTFs ...

  5. CTF各种资源:题目、工具、资料

    目录 题目汇总 Reverse 签到题 Web Web中等难度 Crypto 基础网站 各类工具 综合 Web Payloads 逆向 Pwn 取证 题目汇总 这里收集了我做过的CTF题目 Rever ...

  6. scala 对一个数组分组操作

    通常我们有一些需求,对一个数组两两进行翻转,通常就涉及到奇数偶数,否则就会出现数组index异常了,所以我们该怎么办呢? 虽然是一个入门级问题,但是我还是觉得这是一个很有意思的题目,因此写了一个对于通 ...

  7. 放养的小爬虫--豆瓣电影入门级爬虫(mongodb使用教程~)

    放养的小爬虫--豆瓣电影入门级爬虫(mongodb使用教程~) 笔者声明:只用于学习交流,不用于其他途径.源代码已上传github.githu地址:https://github.com/Erma-Wa ...

  8. [Liferay6.2]Liferay入门级portlet开发示例

    什么是Portlet 来自百度百科(http://baike.baidu.com/view/58961.htm)的定义如下: portlet是基于java的web组件,处理request并产生动态内容 ...

  9. MVC + EF + Bootstrap 2 权限管理系统入门级(附源码)

    MVC .EF 学习有大半年了,用的还不是很熟练,正好以做这样一个简单的权限管理系统作为学习的切入点,还是非常合适的. 开发环境: VS 2013 + Git + MVC 5 + EF 6 Code ...

随机推荐

  1. 使用dcmtk库读取.dcm文件并获取信息+使用OpenCV显示图像

    借助VS2013和OpenCV的绘图功能,在工程DICOMReader.sln中实现了对单张.dcm图像的读取与显示,以下是详细步骤. 前期准备工作 编译器:VS2013 库:dcmtk-3.6.0( ...

  2. 常用开发库 - 告別BeanUtils拷贝,MapStruct工具库最全详解

    常用开发库 - MapStruct工具库详解 MapStruct是一款非常实用Java工具,主要用于解决对象之间的拷贝问题,比如PO/DTO/VO/QueryParam之间的转换问题.区别于BeanU ...

  3. mongodb安装及常见命令操作

    Mongodb是一个介于关系数据库和非关系数据库之间的产品(Nosql),是非关系数据库当中功能最丰富,最像关系数据库的,语法有点类似javascript面向对象的查询语言,它是一个面向集合的,模式自 ...

  4. P1781_宇宙总统(JAVA语言)

    //水题 题目背景 宇宙总统竞选 题目描述 地球历公元6036年,全宇宙准备竞选一个最贤能的人当总统,共有n个非凡拔尖的人竞选总统,现在票数已经统计完毕,请你算出谁能够当上总统. 输入输出格式 输入格 ...

  5. 依赖反转原则DIP 与使用了Repository模式的asp.net core项目结构

    DIP 依赖反转原则 Dependency Inversion Principle 的定义如下: 高级别的模块不应该依赖于低级别的模块, 他们都应该依赖于抽象. 假设Controller依赖于Repo ...

  6. (数据科学学习手札114)Python+Dash快速web应用开发——上传下载篇

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  7. SFDC Trigger里before和after的区别

    最近项目开始用Trigger来进行Validation Check.也知道可以通过配置Object里的Validation Rule来进行Check,但是项目想如果有Trigger里就都在Trigge ...

  8. Starting Tomcat v9.0 Server at localhost' has encountered a problem

    •问题描述 在通过 Eclipse 打开 Tomcat 时报错: •解决方案 找到 Tomcat 的安装位置,打开 tomcat\bin 目录,找到 shutdown.bat,手动关闭 tomcat: ...

  9. MySQL-一条sql语句的执行顺序

    手写: SELECT DISTINCT <select_list> FROM <left_table> <join_type> JOIN <right_tab ...

  10. Install Tensorflow object detection API in Anaconda (Windows)

    This blog is to explain how to install Tensorflow object detection API in Anaconda in Windows 10 as ...