1625-5 王子昂 总结《2017年10月22日》 【连续第387天总结】
A. Xpoint-暨南大学校赛
B.
今天有点晚了╮(╯_╰)╭推迟到零点结束,最后正好赶着把盲水印给搞定了
明天还有课,今天就先把Re的WP写好吧~明天有空的话写下misc的~
这次做题都忘了先查壳,还好一个壳都没有233
3倍
exe直接拖入IDA反编译
找不到入口点和关键函数,直接Shift+f12查找字符串
一眼就看到了Yes和No,双击进入IDA View
然后选中字符串,按x查看交叉引用,向上溯源到调用的地方:
再次双击,就来到了关键函数:
结构非常简单,就是接收int类型的输入,要求乘3后等于0x05C3F6EA
不过怎么说它也是个题目,要是真的一除就出来了也太简单了不是~
计算器计算一下,发现无法整除3
这个套路正好前两天在Reversing.kr上做过,轻车熟路
无法整除3怎么办?
说明真正得数不是0x05C3F6EA, 而是有部分值被溢出抛弃了
3*v5>2**64,溢出部分就没有记录了
那么穷举抛弃部分即可
python3脚本:
i = 1
while(1):
p = i*0x100000000 + 0x5C3F6EA
if(p%3 == 0):
break
else:
i += 1
print(p//3)
瞬间得到输出,提交给程序确认可以返回Yes
题目还提示要以字母形式输出,那么整数转字符用什么方法?当然是hex啦:
在原来的脚本上添加
print(bytes.fromhex(hex(p//3)[2:]))
即可
combo
下下来发现是个APK
拖入APK改之理或者AndroidKiller之类的反编译工具
在MainActivity中就能看到JAVA源码了:
函数很简单,Click事件要求点击201710次
当满足条件的时候将showFlag控件的文本改为2131099682
很明显这并不是flag,而是一个资源的id
这个类中没有相关的说明,我们再去别的类找找
然后在R.Class中查找到了对应的内容(逆向要善用Ctrl+F哦)
看到了变量名是galf,就是flag的逆序嘛,那么很明显关键的内容还藏着呢,接着找~
Class里看完了没有找到东西,我们去APK的整个资源里找一下呗
看,这样就搜索到了~
这种简单的方法仅针对字符串全部明码(硬编码)存放在数据中的
除此以外还可以动态调试APK,修改计数变量的值,令它直接改为201710就能显示flag了,相关过程我之前的总结有写过,就不再赘述了~
还有一种方法,就是直接修改源码,重新生成APK来运行
注意不能修改java源码哦,只能修改Android的汇编-Smali代码:
if(clkAcount==201710)的对应代码在这里
if-ne表示v0和v1不等的话就跳到cond_2处
v1在上一行进行了定义,v0在更上一行,可以看到就是clkAcount变量
爆破这行,将if-ne改为if-eq, 将v0改为v1等等方法都行,只要让它恒成立就OK了
保存后重新编译生成APK,安装运行,轻轻一点即可:
xor
这题就是最简单的入门题了
拖入IDA反编译,跟之前一样查找字符串-查看交叉引用
可以看出,Str1是接收输入的变量,之后与Str2进行比对,相同即通过
Str2来自于sub_411253的修改:
很简单,a1就是Str2的指针,相当于Str2[i] = i ^ data[i];
data是一个硬编码的数组,通过IDC脚本Dump出来脚本生成一下即可:
python3脚本:
d = [102, 109, 99, 100, 127, 99, 55, 117, 123, 125, 85, 120, 120, 104, 55, 46, 49, 108]
for i in range(18):
print(chr(i ^ d[i]), end='')
密码生成器
这题稍微有点复杂了~
提示说是依靠时间生成的密码,只有一个不完整的源码
解压出来发现没有exe后缀名,用记事本/十六进制查看器打开发现文件头标识是ELF
说明是Linux下的可执行文件哦
先拖入IDA反编译吧
这次源码直接就在main函数中乖乖等我们看了呢
time.h相关的函数百度查一下就能得到说明
循环生成密码,可以看出来v8不断被赋值,应该就是密码了
所以说缺少的部分就是不打印了嘛╮(╯_╰)╭
注意这题有一个关键攻击点就是随机函数rand()
它其实是伪随机函数,程序依靠一个算法以srand(seed)的seed来建立一个序列,每次rand都会从中读出一个数字
换句话说,只要seed相同,rand读出的数字也会是完全相同的
这也是提示说密码生成来自时间的原因啦
具体算法不用太关心,直接复制粘贴到C++编译器里就行咯
为什么要用C++编译器而不用Python呢?
因为涉及随机数发生器,乱搞环境会出问题的呀!
(才不是因为我懒得把IDA的C++生成代码转成Python代码了呢~)
注意Byte*(i + 0x804A030)实际上就是指针+下标的数组访问法
因此byte_0x804A030数组还是要Dump出来,复制过去滴
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//2017年10月13日22时08分57秒
//linux的随机数序列不同,必须在linux下运行
void main()
{
time_t p;
struct tm* t;//时间结构体指针
int i;
int data[12]={33, 167, 153, 80, 119, 18, 35, 57, 97, 2, 160, 72};// 复制过来的数组
char v8[20]={0};
printf("%s\n", v8);
p = time(NULL);//得到现在时间
//printf("%d\n",p);
t = localtime(&p);//将时间转换成结构体
t->tm_year = 2017 - 1900;//按照提示中所给的时间写入
t->tm_mon = 10 - 1;
t->tm_mday = 13;
t->tm_hour = 22;
t->tm_min = 8;
t->tm_sec = 57;
p = mktime(t);//将结构体转换回秒数
printf("%d\n",p);
srand(p);//初始化随机数发生器
for ( i = 0; i <= 11; ++i )
{
for ( (v8[i]) = rand() % 80 + data[i];
(v8[i]) <= 64;
(v8[i]) += 26 )
{
;
}
while ( (v8[i]) > 122 )
(v8[i]) -= 26;
if ( (v8[i]) > 90 && (v8[i]) <= 96 )
(v8[i]) -= 43;
}
printf("%s\n", v8);//输出密码
system("pause");
}
代码运行好了以后生成的密码我怎么提交都不对,检查来检查去也没找到问题
最后想起来源程序是ELF格式的,可能在Linux环境下有所不同?
源码复制到虚拟机中gcc编译好了一运行,嘿,密码还真不一样~
提交,完成
so fun从提示来看应该是加壳了
我上次接触安卓加壳还是做前年的国赛的时候了……早就忘光啦,过两天有空再搞吧~
总体来说这次的难度适中,re300和re250稍微有些难度但还挺好玩儿的~
win下的re做起来渐渐也得心应手了呢
(ELF和Android的就要命了)
C. 明日计划
reversing.kr