[转组第3天] | 黑盒测试
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天] | 黑盒测试相关推荐
- 软件测试用例的优点和缺点,浅析黑盒测试和白盒测试各自的优缺点
软件测试是为了发现程序中的错误而执行程序的过程,常用黑盒功能测试法和白盒结构测试法进行测试,那黑盒功能测试法和白盒结构测试法到底是什么样的测试方法?它们有哪些优劣势呢? 所谓黑盒功能测试法,就是把要测 ...
- 黑盒法测试c语言,黑盒测试的测试用例设计方法(经典理论知识,推荐)
一.黑盒测试的测试用例设计方法 1. 等价类划分方法 2. 边界值分析方法 3. 错误推测方法 4. 因果图方法 5. 判定表驱动分析方法 6. 正交实验设计方法 7. 功能图分析方法 二.等价类划分 ...
- 黑盒测试实践进度记录(五)
今天是170405组黑盒测试大作业的最后一天:. 滕怡天:编写测试脚本.首先是发布了最初次的脚本,之后使用脚本的成员发现登录有问题,于是又继续高效地完成了登录脚本并发布出来,之后又陆续根据组员的要求改 ...
- 学生宿舍管理项目开发计划书_第六组学生宿舍管理系统项目计划书
组长:高仁英 成员:杨舒婷.连燕婷 1.引言 1.1目的 [1]本章提供整个软件开发计划的综述,主要确定以下内容: [2]软件生存周期的选取及裁剪. [3]软件规范.方法和标准的选择. [4]软件工作 ...
- 软件单元黑盒测试,软件测试教学资源单元3 黑盒测试.doc
软件测试教学资源单元3 黑盒测试 <软件测试>课程教学单元设计 单元3 黑盒测试-网上订餐系统的测试授课教师: 课程组授课班级: :教学条件软件平台.投影设备.广播软件.互联网教学素材参考 ...
- 黑盒测试、白盒测试与灰盒测试方法
测试奇谭,BUG不见. 大家好,我是谭叔. 对于黑盒.白盒与灰盒测试方法的理解,几年前我在某乎做过一个概念性的回答,当时提问者询问:如何跟非技术人员解释黑盒.白盒.灰盒测试的区别? 我的回答原文如下: ...
- (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 监控 ...
- 2.10黑盒测试-常见输入输出方式
单点测试:一组通过就有分数,最后看分数之和. 多点测试:全部数据通过才算通过. 1.常用的输入方式:(1) while...EOF型 如果题目没有给定输入的结束条件,那么就默认读取到文件末尾.对黑盒测 ...
- 第三组 通信一班 030 网工知识点总结
2019年软考网络工程师考点一:局域网技术 VTP协议 在VTP域中有个很重要的概念就是交换机的模式,分别是服务器模式.客户端模式.透明模式. 服务器模式的交换机可以添加.修改.删除VLAN以及V ...
- 测试基础-动态黑盒测试
1.动态黑盒测试 不深入代码细节测试软件的方法称为动态黑盒测试. 动态:因为程序在运行: 黑盒:测试时不知道程序如何工作. 测试员输入数据.接受输出.检验结果. 2.通过性测试和失效性测试 通过性测试 ...
最新文章
- IPSEC传输模式和隧道模式的区别
- kylin KV+cube方案分析
- Python字符串常用函数详解
- php选择排序算法原理_PHP排序算法之选择排序
- 彻底理解 Python 生成器
- edtext 从右边开始输入 安卓_转换iOS和安卓的视频至任何格式
- Eclipse自定义文档注释和方法注释
- html 判断IE版本并加载对应的css,js
- 计算机一级选择题比大小,科学网—【2年前写的】全国计算机等级考试 【三级网络】考试经验 - 钱世杰的博文...
- jsp教师档案信息管理系统ssh
- python 画图工具——matplotlib命令式函数
- CSO246未能找到类型或命名空间名“System“(是否缺少using指令或程序集引用?)
- 聊聊传统行业产品经理与互联网产品经理的区别
- C++在一个类中定义另一个有参数构造函数的类的对象
- SDL(Simple DirectMedia Layer) 简介
- 【无标题】前端电子签名的canvas画板
- DC888 : 数据流分析
- 搭建项目框架时需要考虑的几个问题
- 专注力的重要性和提高的方法
- python3.6安装库_python3.6怎么安装库