2018-04-26

DDCTF(re2):Reverseme.elf 参照夜影大佬的wp

  这个题目的代码清晰透明,没有各种花指令,混淆等操作,按夜影大佬说法,是个硬核分析题。

  

  重点说一下数据结构的定义:程序在上图第一个红框里进行结构体的初始化,在new(v4)中也有部分初始化,不过重点是在genstruct这个构造函数中。

  嗯,从夜影大佬那里学的分析数据结构很重要,虽然代码结构明显,但是后面各种指针乱飞,看的晕晕乎乎,分析题目如果有比较重要的结构体,特别是存储输入字符串相关的结构体,最好要分析透彻再继续。

偏移 类型 长度 备注
a1 sth_p qword 0x100(sth)  
a1+8 char_table_0_p qword 0x100(char_table_0) byte(char_table_0)
a1+16 input(char) byte 0x64  
a1+272 rand%50      
a1+280 char_table_0_p-sth_p qword   *(a1+8) - *a1
a1+288+8 char_table_2 dword 9  
a1+408 char_table_1 byte 255  
a1+672 func_addr qword   临时变量,指向func_table中某值
a1+672+8 func_table qword 255 表内9个指定位置函数会被修改

  关于后面提到的*(a1+664),*(a1+665)等的初始化,均在new(v4)中实现。

  genstruct(v4)初始化了上述结构体,接下来进行输入,然后到达check函数,看一下check函数。

  

  写成python伪代码:

1 for i in range(len(input)):
2     *(a1+664) = input[i+1]
3     for j in range(8):
4         if (f[input[i]] == (a1+408)[(a1+288+8)[j]]):
5             *(a1+672) = (a1+672+8)[(a1+288+8)[j]]
6             call *(a1+672)(a1)

  注意:将IDA的结构体写成高级语言的数组时,尽量将4*i,8*i等偏移卸掉,因为显然4,8是数组的元素大小,将其卸掉写成(addr)[i]的形式更容易理解,也更容易和上面分析出来的结构体对应。举个例子:

*(a1 + *(a1 + 4 * (j + 72) + 8) + 408)  --> (a1+408)[(a1+288+8)[j]])把固定偏移72乘出来*(a1 + *(a1 + 288 + 8 + 4 * j) + 408)可以看出a1+288+8是上述结构体中的偏移,存储char_table_2,且该表元素类型是dword,4字节对应4*j.改写如下*(a1 + (a1 + 288 + 8)[j] + 408)再观察发现a1+408也是上述结构体中的偏移,存储char_table_1,且该表元素类型是byte,1字节正好对应。改写如下(a1 + 408)[(a1 + 288 + 8)[j]]如果还觉得不好理解还可以直接替换成char_table等自己定义的别名如下,不过不建议这么做,因为或许其他地方还会有各种指针偏移出现,过于抽象高级反而不好跟前面分析出的结构体对应。char_table_1[char_table_2[j]]

  嗯,这是一种好的分析习惯,分析结构体,因数替换。

  接着看上面check代码,实际上就是令Input[i]作为下标取数组f的值,然后遍历char_table_1中的9个值,如有相等的则取func_addr中对应的函数来调用。可以定位到那9个函数。逐个反编译:

 1     func_0:
 2         if(*(a1+288)<*(a1+292)):
 3             *(a1+665) = char_table_0[*(a1+288)]
 4     func_1:
 5         if(*(a1+288)<*(a1+292)&& *(a1+665)):
 6             char_table_0[*(a1+288)]  = *(a1+665)
 7     func_2:
 8         if(*(a1+288)<*(a1+292)):
 9             *(a1+665) = *(a1+665)+*(a1+664)-33
10     func_3:
11         *(a1+665) = *(a1+665)-(*(a1+664)-33)
12         if(*(a1+288)<*(a1+292) && *(a1+665) == 0):
13             *(a1+665)++;
14     func_4:
15         if(*(a1+288)<*(a1+292)):
16             *(a1+288)++;
17     check_func:
18         *(a1+664) == 's'
19         s = char_table_0[*(a1+288) +i] len=20
20         if(check(s))->sucess
21     func_6:
22         if(*(a1+288)>0):
23             *(a1+288)--;
24     func_7:
25         if(*(a1+288)<*(a1+292)&&*(a1+664)<=0x59):
26             char_table_0[*(a1+288)] = input[*(a1+288)+*(a1+664)-48]-49
27     func_8:
28         for(i=0;*(a1+664)>i;++i)
29             *(a1+288)++;
30         if(*(a1+664)<=0x69)
31             char_table_0[*(a1+288)] = input[*(a1+288)+*(a1+664)-48]-49

  其中用到的变量一共有4个

*(a1+664) = [next]
*(a1+292) = 255
*(a1+288) = index 0
*(a1+665) = m(临时变量) 0

  再优化一下func:

 1 index = 0,range = 255,m = 0 ,[next]
 2 func_0:
 3     if(index<255):
 4         m = char_table_0[index]
 5 func_1:
 6     if(index<255&& m):
 7         char_table_0[index]  = m
 8 func_2:
 9     if(index<255):
10         m = m+[next]-33
11 func_3:
12     m = m-([next]-33)
13     if(index<255 && m == 0):
14         m++;
15 func_4:
16     if(index<255):
17         index++;
18 func_6:
19     if(index>0):
20         index--;
21 func_7:
22     if(index<255&&[next]<=0x59):
23         char_table_0[index] = input[index+[next]-48]-49

  在check_func中会输出s,s是从char_table_0中以index为起点取的0x20个值。如果s满足三个方程则通过校验,返回成功

  而实际上那三个方程是不需要逆的—题目中明示了只要输出“Binggo”即可得到flag。仔细读题很重要!

  因此目标显然是在char_table_0中获得Binggo的字符串,将其dump出来输出了一下发现并字符顺序并没有合适的,甚至上述5个字母都不齐以及一个最关键的问题,check_func中取了0x20个值赋给s,这显然不符合”Binggo”的要求,因此第七个字符必须给上’\0’使其截断才行。

  分析其余8个函数,发现0和1可以交换char_table_0中的字符的位置,2、3和7、8则可以修改char_table_0中字符的值,4和6则是用来移动下标的,最后check_func加’s’来结束并输出。

  在构造输入之前,先要找到函数对应的输入值,IDA动态调试断在函数调用处调用idc脚本即可得到对应值:IDC脚本很重要!

 1 #include<idc.idc>
 2 static main()
 3 {
 4     auto i, j, v14, p, q;
 5     for(i=0;i<=8;i++)
 6     {
 7         p = Byte(0xc1e440+288+8+4*i);
 8
 9         v14 = Dword(0xc1e440+672+8+8*p);
10
11         for(j=0;j<255;j++)
12         {
13             if(Byte(0x603900+j)==Byte(0xc1e440+408+p))
14             {
15                 q = j;
16                 break;
17             }
18             //Message("Not Found : %x", Byte(0x603700+p));
19         }
20         Message("%x\t%c\t%x\n",q , q, v14);
21     }
22     Message("finish\n");
23 }
24
25 //得到输出
26     24  $   400dc1
27     38  8   400e7a
28     43  C   400f3a
29     74  t   401064
30     30  0   4011c9
31     45  E   40133d
32     75  u   4012f3
33     23  #   4014b9
34     3b  ;   400cf1

  得到这9个输入字符即可开始构造了 ,由于函数功能很多样,因此构造方法很多,在此仅表述我的构造方法:思路也参考夜影大大

  思路:由于输入buffer有限,因此不适合向右移动指针太多来找寻合适的字符。所以我就原地变换—毕竟将一个字符变成另一个字符满打满算也只要4个输入,移动指针可就轻而易举几十上百了。

  

  |func|$   0    m = 0x50
t   3   m = m - ([next]-33) = 0x50 - (0x2f-33) = 0x42   --->'B'
/
8   1    char_table_0[0] = 0x42('B')
0   4   index++;
$   0   m = 0x61
C   2   m = m + [next]-33 = 0x61 + 0x29 -33 = 0x69   --->'i'
)
8   1    char_table_0[1] = 0x69('i')
0   4   index++;
$   0   m = 0x46
C   2   m = m + [next]-33 = 0x46 + 0x49 -33 = 0x6e   --->'n'
I
8   1    char_table_0[2] = 0x6e('n')
0   4   index++;
$   0   m = 0x30
C   2   m = m + [next]-33 = 0x30 + 0x58 -33 = 0x67   --->'g'
X
8   1    char_table_0[3] = 0x67('g')
0   4   index++;
$   0   m = 0x21
C   2   m = m + [next]-33 = 0x21 + 0x67 -33 = 0x67   --->'g'
g
8   1    char_table_0[4] = 0x67('g')
0   4   index++;
$   0   m = 0x26
C   2   m = m + [next]-33 = 0x26 + 0x6a -33 = 0x6f   --->'o'
j
8   1    char_table_0[5] = 0x6f('o')
0   4   index++;  //index=6
1
#   7    char_table_0[6] = input[6+72-48]-49 = input[30]-49 = 49-49 =0 --->'\0'
H
u
u
u
u
u
u  index归0
Es 触发check_func

最终str:$t/80$C)80$CI80$CX80$Cg80$Cj801#HuuuuuuEs

  在linux上运行测试:

  

  提交给服务器即可获得flag。

  总结:

    好的分析习惯:分析结构体,因数替换。

    仔细读题很重要!

    IDC脚本很重要!

  明天预计:

    DDCTF re3,

    了解了解android安全怎么搞?菜哭

转载于:https://www.cnblogs.com/nww-570/p/8954214.html

[转组第3天] | 黑盒测试相关推荐

  1. 软件测试用例的优点和缺点,浅析黑盒测试和白盒测试各自的优缺点

    软件测试是为了发现程序中的错误而执行程序的过程,常用黑盒功能测试法和白盒结构测试法进行测试,那黑盒功能测试法和白盒结构测试法到底是什么样的测试方法?它们有哪些优劣势呢? 所谓黑盒功能测试法,就是把要测 ...

  2. 黑盒法测试c语言,黑盒测试的测试用例设计方法(经典理论知识,推荐)

    一.黑盒测试的测试用例设计方法 1. 等价类划分方法 2. 边界值分析方法 3. 错误推测方法 4. 因果图方法 5. 判定表驱动分析方法 6. 正交实验设计方法 7. 功能图分析方法 二.等价类划分 ...

  3. 黑盒测试实践进度记录(五)

    今天是170405组黑盒测试大作业的最后一天:. 滕怡天:编写测试脚本.首先是发布了最初次的脚本,之后使用脚本的成员发现登录有问题,于是又继续高效地完成了登录脚本并发布出来,之后又陆续根据组员的要求改 ...

  4. 学生宿舍管理项目开发计划书_第六组学生宿舍管理系统项目计划书

    组长:高仁英 成员:杨舒婷.连燕婷 1.引言 1.1目的 [1]本章提供整个软件开发计划的综述,主要确定以下内容: [2]软件生存周期的选取及裁剪. [3]软件规范.方法和标准的选择. [4]软件工作 ...

  5. 软件单元黑盒测试,软件测试教学资源单元3 黑盒测试.doc

    软件测试教学资源单元3 黑盒测试 <软件测试>课程教学单元设计 单元3 黑盒测试-网上订餐系统的测试授课教师: 课程组授课班级: :教学条件软件平台.投影设备.广播软件.互联网教学素材参考 ...

  6. 黑盒测试、白盒测试与灰盒测试方法

    测试奇谭,BUG不见. 大家好,我是谭叔. 对于黑盒.白盒与灰盒测试方法的理解,几年前我在某乎做过一个概念性的回答,当时提问者询问:如何跟非技术人员解释黑盒.白盒.灰盒测试的区别? 我的回答原文如下: ...

  7. (13.1.2)PMBOK之二:五大过程组及其涉及的输入、输出、工具技术

    一.五大过程组概述 1.1 过程的定义 1.2 五大过程组的由来 1.3 五大过程组49 1.3.1 启动 2 13% 1.3.2 规划 24 24% 1.3.3 执行 10 30% 1.3.4 监控 ...

  8. 2.10黑盒测试-常见输入输出方式

    单点测试:一组通过就有分数,最后看分数之和. 多点测试:全部数据通过才算通过. 1.常用的输入方式:(1) while...EOF型 如果题目没有给定输入的结束条件,那么就默认读取到文件末尾.对黑盒测 ...

  9. 第三组 通信一班 030 网工知识点总结

    2019年软考网络工程师考点一:局域网技术   VTP协议 在VTP域中有个很重要的概念就是交换机的模式,分别是服务器模式.客户端模式.透明模式. 服务器模式的交换机可以添加.修改.删除VLAN以及V ...

  10. 测试基础-动态黑盒测试

    1.动态黑盒测试 不深入代码细节测试软件的方法称为动态黑盒测试. 动态:因为程序在运行: 黑盒:测试时不知道程序如何工作. 测试员输入数据.接受输出.检验结果. 2.通过性测试和失效性测试 通过性测试 ...

最新文章

  1. IPSEC传输模式和隧道模式的区别
  2. kylin KV+cube方案分析
  3. Python字符串常用函数详解
  4. php选择排序算法原理_PHP排序算法之选择排序
  5. 彻底理解 Python 生成器
  6. edtext 从右边开始输入 安卓_转换iOS和安卓的视频至任何格式
  7. Eclipse自定义文档注释和方法注释
  8. html 判断IE版本并加载对应的css,js
  9. 计算机一级选择题比大小,科学网—【2年前写的】全国计算机等级考试 【三级网络】考试经验 - 钱世杰的博文...
  10. jsp教师档案信息管理系统ssh
  11. python 画图工具——matplotlib命令式函数
  12. CSO246未能找到类型或命名空间名“System“(是否缺少using指令或程序集引用?)
  13. 聊聊传统行业产品经理与互联网产品经理的区别
  14. C++在一个类中定义另一个有参数构造函数的类的对象
  15. SDL(Simple DirectMedia Layer) 简介
  16. 【无标题】前端电子签名的canvas画板
  17. DC888 : 数据流分析
  18. 搭建项目框架时需要考虑的几个问题
  19. 专注力的重要性和提高的方法
  20. python3.6安装库_python3.6怎么安装库

热门文章

  1. 同步京东、抖音、淘宝等多处订单到本地商城,这里只举例京东同步
  2. Sentinel-1A数据 GRD和SLC的区别
  3. HDU5211——Mutiple
  4. c语言实训自我总结报告,C++实训总结报告
  5. 科技论文写作课程笔记
  6. 如何用计算机的if,if函数的使用方法(if函数的使用方法)
  7. 如何高效的利用谷歌学术搜索文献
  8. iOS ipa包解析
  9. 阿尔兹海默症AD最新研究进展(2022年2月)
  10. 在这里,北上深成为“社科之城”