安恒杯10月月赛两道逆向2018.10.27

这次两道逆向题都用到了base64加密,参看:base64由来、原理及代码实现

两道题目及脚本链接:链接
提取码:6oc7

一、easytree

给出的是一个没有后缀的文件,经过查看是一个exe程序:


eyuhVu7.png

加上后缀,运行程序:


PTgDlq6.png

打开ida,发现有upx加壳,呵!拉到脱壳机脱壳后,再用ida打开


NkMp1mR.png

可知flag长度为15,经过了三个函数处理,最后和一个字符串比较,若相同则为flag

重点是三个函数的作用:

我们就从下往上看,看sub_401794(&v6);有什么操作:


Gq2C98q.png

明白人一看就知道这是base64加密,因为特点就是在于移位操作,参看:base64加密原理

知道加密方法之后将“aWNuZXJyc2VhZXRydmVl”解密:icnerrseaetrvee

再看上一个函数sub_40166E(v8, v9, (int)&v6);


N5cXRAx.png
/递归方式前序遍历二叉树
void PreOrderTraverse(BiTree T, int level)
{
    if (T == NULL)
        return;
/*此处表示对遍历的树结点进行的操作,根据你自己的要求进行操作,这里只是输出了结点的数据*/
    //operation1(T->data);
    operation2(T->data, level); //输出了层数
    PreOrderTraverse(T->lchild, level + 1);
    PreOrderTraverse(T->rchild, level + 1);
}

输入为flag,只看算法就是递归将flag相应的位给了新的地址,最后返回结果,最后应该是将flag乱序排列,至于乱序排列的顺序,不知道,但是题目给了tree提示,那不就是二叉树嘛,二叉树的遍历就用到了递归,然后观察代码应该是个前序遍历,到这就知道了,这个函数返回地是遍历结果:icnerrseaetrvee

复原不就是按照前序结果复原二叉树吗?前序都知道,第一个是跟节点,经过复原:


B5ENcfl.png

这时候,就可以猜到flag,按层序读:icanreversetree,猜想应该是按层序建立的二叉树,然后通过先序遍历二叉树,之后再经过base64加密得到密文。

其实也可以用OD跟出第二个函数排列之后的顺序:

输入15位:abcdefghijklmno


jpWi48o.png

跟出的结果:abdhiejkcflmgno

abcdefjhijklmno
abdhiejkcflmgno
根据这个顺序可以将解密后的密文按照上面顺序再排列:

icnerrseaetrvee
icanreversetree

也可以得到flag

二、BASE++

运行程序:


12.png

拖进ida:


13.png

首先输入flag,判断长度是否小于32,小于的话就跳转,不小于的话,就进行transform_1((const char )&input_flag);,然后transform_2();,transform_3(strlen((const char )&input_flag), (int)&input_flag, (int)a0);之后比较返回结果和”TRLT5amLBoLT5Z6Fa5LqN6mkTomqR66Da4LqX5mgBwkkP5wmTZ6D====”比较,相等返回0,则程序可以输出Congratulations!!!
看见显眼的=号base64,32解密一下,无果,怪不得题目名字叫base++,可能是又改了东西。

1.看第一个函数transform_1((const char *)&input_flag);

目的:仅对flag大小写字母进行移位操作


14.png

2.transform_2();函数:

数组内容:’ABCDEFGHIJKLMNOPQRSTUVWXYZ’

目的:对密码表进行变换操作


15.png

3.transform_3(strlen((const char *)&input_flag), (int)&input_flag, (int)a0);函数:

目的:对flag进行加密,每5个字符生成一个数值v4,将v4移位后分成5位二进制数作为密码表的索引下标,加密方法类似于base32,但是密码表是出题人自己定义的。


16.png

base_tran_5(v3 + input_flag, v5, v4);函数


17.png

分析到这,来整理一下思路:

现在还没有确定flag长度,但根据分析函数flag5位-》密文8位 可知长度位32,

1.将flag进行变换

2.对密码表进行变换

3.对flag进行每5个字符加密,生成8个5位二进制数,在密码表索引密文最后生成密文

例:

在这里给一下思路 该代码每次使用五个字符

比如我输入

abcdefghijklmn
那么先取abcde

在内存中就是6162636465

eax只存62636465 edx存00000061

6162636465 换成二进制就是

0110000101100010011000110110010001100101

每五个位分成一组

01100 00101 10001 00110 00110 11001 00011 00101

每一组换成十进制后当成序号取密码表中的值换成密文

脚本:

    # coding=utf-8
def transform_1(flag):
    v2 = 0
    while v2<len(flag):
        v3 = ord(flag[v2])
        if (abs(v3-97)<=25):
            flag[v2] = chr((v3 - 84) % 26 + 97)
        if (abs(v3-65)<=25):
            flag[v2] = chr((v3 - 52) % 26 + 65)
        v2+=1
    return flag
#生成密码表
str=list("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
def transform_2(str):
    transform_1(str)
    slen=len(str)
    for i in range(slen):
        if i%2==1:
            str[i]=chr(ord(str[i])+32)
    str.append("7")
    str.append("6")
    str.append("5")
    str.append("4")
    str.append("3")
    str.append("2")
    return str
print (transform_2(str))

byte=['N', 'o', 'P', 'q', 'R', 's', 'T', 'u', 'V', 'w', 'X', 'y', 'Z', 'a', 'B', 'c', 'D', 'e', 'F', 'g', 'H', 'i', 'J', 'k', 'L', 'm', '7', '6', '5', '4', '3', '2']
enc=list("TRLT5amLBoLT5Z6Fa5LqN6mkTomqR66Da4LqX5mgBwkkP5wmTZ6D2222")
#返回密文在密码表中的下标
def index(s):
    for i in range(32):
        if s==byte[i]:
            return i

#解密
for i in range(0,56,8):
    v=7
    flag=0
    for j in range(8):
        flag+=index(enc[i+j])<<5*v
        v-=1
    print ("%x"%flag)

#16进制变ASCII字符
flagstr="31306e373870706e33726f30306f373072326f706f70357333726f71713933370ffff"
a1=[]
for i in  range(0,len(flagstr),2):
    s=flagstr[i:i+2]
    a1.append(chr(int(s,16)))
print (a1)
#最后对flag进行变换
for i in range(32):
    if 97<ord(a1[i])<123:
        a1[i]=chr(ord(a1[i])-97+84)
    if 65<ord(a1[i])<90:
        a1[i]=chr(ord(a1[i])-65+52)
print ("".join(a1))

结果验证:


18.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值