第五届TSCTF-RE部分题解

前言

这个周末参加了一下北邮的TSCTF,可以明确感觉到自己目前缺的是处理数据的工具或者是更高的技巧,许许多多的知识待补!有幸认识了在北邮读研的直系学长,也算是一些收获。

RE1 Checkin

分析

elf文件,IDA观察查看程序很简单。没仔细看,先上动调看看。

这里处理的第一步首先循环右移数据 ror flag[x],x

在这里插入图片描述

然后是直接进行已知字符对比验证。

1557708917765

exp

a=[0x54,0xa9 ,0xd0 ,0x8a ,0x64 ,0xdb ,0x1d ,0x80 ,0x6d ,0x99 ,0xd7 ,0x6e ,0x45 ,0x0b ,0xc9 ,0xe8,0x5f,0xbe]
  
#int_value是输入的整数,k是位移的位数,bit是整数对应二进制的位数
# right circular shift
  
def circular_shift_right (int_value,k,bit = 8): 
 bit_string = '{:0%db}' % bit 
 bin_value = bit_string.format(int_value) # 8 bit binary 
 bin_value = bin_value[-k:] + bin_value[:-k] 
 int_value = int(bin_value,2) 
 return int_value
  
  
if __name__ == "__main__": 
 for i in range(len(a)):
     for j in range(48,128):
         m=i
         m=m%8
         if circular_shift_right(j, m, 8) == a[i]:
             print(chr(j),end='')

总结

算是签到题,循环右移算法python没有自带的,我在网上找的一个算法。不过也不难


RE2

分析

在IDA查看,这个程序静态观察的很清楚。输入一个字符串之后经过两个验证即可通过。

1557709136192

check1 进行格式验证,为TSCTF{xx},长度为23。然后是对数据进行简单的对表替换,可以暂时不看

1557709240038

check2首先将数据处理,然后进行tea加密。解题时候看见不是很好做的算法加密首先会想一下是不是已知的算法,查了一下题目tea找到了解密算法。将key换成题目中的key即可。

1557709331113


#include <stdio.h>
#include <stdint.h>
 
//加密函数
void encrypt (uint32_t* v) {
    uint32_t v0=v[0], v1=v[1], sum=0, i;           /* set up */
    uint32_t delta=0x9e3779b9;                     /* a key schedule constant */  /* cache key */
    for (i=0; i < 32; i++) {                       /* basic cycle start */
        sum += delta;
        v0 += ((v1<<4) + 0x19260817) ^ (v1 + sum) ^ ((v1>>5) + 0x11111111);
        v1 += ((v0<<4) + 0x424255AA) ^ (v0 + sum) ^ ((v0>>5) - 0x5D2CED22);
    }                                              /* end cycle */
    v[0]=v0; v[1]=v1;
}
//解密函数
void decrypt (uint32_t* v) {
    uint32_t v0=0x2B31EA2B, v1=0xAEEDFCAD, sum=0xC6EF3720, i;  /* set up */
    uint32_t delta=0x9e3779b9;                     /* a key schedule constant */  /* cache key */
    for (i=0; i<32; i++) {                         /* basic cycle start */
        v1 -= ((v0<<4) + 0x424255AA) ^ (v0 + sum) ^ ((v0>>5) - 0x5D2CED22);
        v0 -= ((v1<<4) + 0x19260817) ^ (v1 + sum) ^ ((v1>>5) +0x11111111);
        sum -= delta;
    }                                              /* end cycle */
    v[0]=v0; v[1]=v1;
}
 
int main()
{
    uint32_t v[2]={937345,1669424};
    // v为要加密的数据是两个32位无符号整数
    // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
    printf("加密前原始数据:%u %u\n",v[0],v[1]);
    encrypt(v);
    printf("加密后的数据:%u %u\n",v[0],v[1]);
    decrypt(v);
    printf("解密后的数据:%u %u\n",v[0],v[1]);
    return 0;
}

之后先将已知字符两两一组进行解密,需要注意的是,解密后如果超过无符号数表达值,只需要减去0x100000000即可转化为负数。

1557709517372

解密后得到的数据,再往回推就是上面的比较直观的处理了。16个未知数16个方程组,使用Z3解答。

我这里比较笨,手动输入的系数,我知道肯定有更好的办法,比如写个自动化处理字符的脚本之类的,唉 头铁了

from z3 import *
x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,x16=Ints('x1 x2 x3 x4 x5 x6 x7 x8 x9 10 x11 x12 x13 x14 x15 x16')
f = Solver()
f.add(x1*(0xfffff172-0x100000000)+x2*0xca85+x3*0xa3e2+x4*0x8fde+x5*(0xffffbf21-0x100000000)+x6*(0xffff2ba8-0x100000000)+x7*(0xfffff36e-0x100000000)+x8*(0xffffb706-0x100000000)+x9*(0xffffc169-0x100000000)+x10*(0xfffff41d-0x100000000)+x11*(0xffff88b4-0x100000000)+x12*(0xffffd72d-0x100000000)+x13*0x3f5a+x14*(0xffffac52-0x100000000)+x15*0x821c+x16*0xfa44==3143859)

f.add(x1*0x9859+x2*0xcade+x3*0xa561+x4*0x5a8f+x5*(0xffffc6bf-0x100000000)+x6*(0xffff2d87-0x100000000)+x7*(0xfffff5a3-0x100000000)+x8*(0xffffb8c6-0x100000000)+x9*(0xffffcdca-0x100000000)+x10*(0xffffcf72-0x100000000)+x11*(0xffff8d08-0x100000000)+x12*(0xffffdf03-0x100000000)+x13*0x2f19+x14*(0xffffac86-0x100000000)+x15*0x81ed+x16*0xe748==8171460)

f.add(x1*(0xfffff172-0x100000000)+x2*0xca85+x3*0xa3e2+x4*0x8fef+x5*(0xffffbf21-0x100000000)+x6*(0xffff2ba8-0x100000000)+x7*(0xfffff36e-0x100000000)+x8*(0xffffb706-0x100000000)+x9*(0xffffc166-0x100000000)+x10*(0xfffff41d-0x100000000)+x11*(0xffff88b8-0x100000000)+x12*(0xffffd72d-0x100000000)+x13*0x3f5a+x14*(0xffffac52-0x100000000)+x15*0x821c+x16*0xfa47==3146919)

f.add(x1*(0xfffff172-0x100000000)+x2*0xc7c1+x3*0xa3eb+x4*0x8ef7+x5*(0xffffc9d8-0x100000000)+x6*(0xffff2ba5-0x100000000)+x7*(0xffff3c39-0x100000000)+x8*(0xffffb6bf-0x100000000)+x9*(0xffffce03-0x100000000)+x10*(0xfffff34b-0x100000000)+x11*(0xffff87ad-0x100000000)+x12*(0xffffd766-0x100000000)+x13*0x2f1e+x14*(0xffffac4e-0x100000000)+x15*0x2c0f+x16*0xf656==-5858067)

f.add(x1*(0xffffecb5-0x100000000)+x2*(0xffff9e87-0x100000000)+x3*0x3088+x4*0x4805+x5*(0xffffbf37-0x100000000)+x6*(0xffff1cc8-0x100000000)+x7*(0xffff7532-0x100000000)+x8*(0xffff0806-0x100000000)+x9*(0xfffff361-0x100000000)+x10*(0xffffd081-0x100000000)+x11*(0xffff8b45-0x100000000)+x12*(0xffffd503-0x100000000)+x13*0x1fba+x14*(0xffff20a8-0x100000000)+x15*0xbd69+x16*0x7d22==-22399063)

f.add(x1*0xd6c+x2*0x1e80+x3*0xa69f+x4*0x8fe3+x5*(0xffffbcf9-0x100000000)+x6*(0xffff2cab-0x100000000)+x7*(0xffff3768-0x100000000)+x8*(0xffffea43-0x100000000)+x9*(0xffffce05-0x100000000)+x10*(0xffffcba4-0x100000000)+x11*(0xffff80e3-0x100000000)+x12*(0xffffaed1-0x100000000)+x13*0xccfc+x14*(0xffffa9f8-0x100000000)+x15*0x2b9b+x16*0xf688==-7081089)

f.add(x1*(0xfffff16a-0x100000000)+x2*0x2f0b+x3*0xa3dc+x4*0x900d+x5*(0xffffbf20-0x100000000)+x6*(0xffff2ba8-0x100000000)+x7*(0xfffff343-0x100000000)+x8*(0xffffb706-0x100000000)+x9*(0xffffc169-0x100000000)+x10*(0xfffff456-0x100000000)+x11*(0xffff8806-0x100000000)+x12*(0xffffd75c-0x100000000)+x13*0x2f1c+x14*(0xffffac50-0x100000000)+x15*0x821b+x16*0xf6e4==937345)

f.add(x1*(0xfffff4a7-0x100000000)+x2*0xc983+x3*0xa3e8+x4*0x8edd+x5*(0xffffbfb2-0x100000000)+x6*(0xffff2c59-0x100000000)+x7*(0xfffff36e-0x100000000)+x8*(0xffffb6cc-0x100000000)+x9*(0xffffcd85-0x100000000)+x10*(0xfffff342-0x100000000)+x11*0x32a+x12*(0xffffd824-0x100000000)+x13*0x3f40+x14*(0xffffac6c-0x100000000)+x15*0x2c08+x16*0xf366==1669424)

f.add(x1*0x91ee+x2*0xcb37+x3*0xa16e+x4*0x8fdc+x5*(0xffffbeb9-0x100000000)+x6*(0xffff2bb6-0x100000000)+x7*(0xffff3bc4-0x100000000)+x8*(0xffffeb2a-0x100000000)+x9*(0xffffce08-0x100000000)+x10*(0xfffff4d8-0x100000000)+x11*(0xfffffcbf-0x100000000)+x12*(0xfffface1-0x100000000)+x13*0xce55+x14*(0xffffacdf-0x100000000)+x15*0x828b+x16*0xaa75==8037239)

f.add(x1*0x1546+x2*0xca8e+x3*0x3a69+x4*0x703c+x5*0x8f78+x6*(0xffff2f60-0x100000000)+x7*(0xffff361c-0x100000000)+x8*(0xffff0877-0x100000000)+x9*(0xffffcdcb-0x100000000)+x10*(0xffffcaa2-0x100000000)+x11*(0xffff703d-0x100000000)+x12*(0xfffff72b-0x100000000)+x13*0x3f5a+x14*(0xffffc1e1-0x100000000)+x15*0x3007+x16*0xe1ff==1157740)

f.add(x1*(0xfffff16f-0x100000000)+x2*0xca85+x3*0xa3e2+x4*0x8fde+x5*(0xffffca92-0x100000000)+x6*(0xffff2ba8-0x100000000)+x7*(0xfffff36d-0x100000000)+x8*(0xffffb705-0x100000000)+x9*(0xffffcd83-0x100000000)+x10*(0xfffff41d-0x100000000)+x11*(0xffff88bc-0x100000000)+x12*(0xffffd72a-0x100000000)+x13*0x3f3d+x14*(0xffffac52-0x100000000)+x15*0x821c+x16*0xfa44==4334495)

f.add(x1*0x738+x2*0x2f12+x3*0x39ae+x4*0x509a+x5*0x2069+x6*(0xffff2ba8-0x100000000)+x7*(0xffffe27e-0x100000000)+x8*(0xfffff15c-0x100000000)+x9*(0xffff2532-0x100000000)+x10*(0xffff110a-0x100000000)+x11*0x7438+x12*(0xfffff264-0x100000000)+x13*0xa9dc+x14*(0xffffdae0-0x100000000)+x15*0x821c+x16*0xd7f9==-7799960)

f.add(x1*(0xfffff172-0x100000000)+x2*0x2f13+x3*0xa3e2+x4*0x8fef+x5*(0xffffca9f-0x100000000)+x6*(0xffff2ba8-0x100000000)+x7*(0xfffff36e-0x100000000)+x8*(0xffffb707-0x100000000)+x9*(0xffffcd82-0x100000000)+x10*(0xfffff41d-0x100000000)+x11*(0xffff88ba-0x100000000)+x12*(0xffffd72a-0x100000000)+x13*0x3f65+x14*(0xffffac52-0x100000000)+x15*0x821c+x16*0xfa47==2513032)


f.add(x1*0x5cb4+x2*0xc5c2+x3*0xa19e+x4*0x8016+x5*0x9a57+x6*(0xffff2f60-0x100000000)+x7*(0xfffff33e-0x100000000)+x8*(0xffffe95d-0x100000000)+x9*(0xffffccc3-0x100000000)+x10*(0xfffff41d-0x100000000)+x11*(0xffff6af6-0x100000000)+x12*(0xffffaed8-0x100000000)+x13*0xdab9+x14*(0xffffad1b-0x100000000)+x15*0x821c+x16*0xb37a==20181947)


f.add(x1*0x7ff0+x2*0xcb26+x3*0xaa9e+x4*0x8766+x5*(0xffffcc29-0x100000000)+x6*(0xffff2d2c-0x100000000)+x7*(0xfffff207-0x100000000)+x8*(0xffffb709-0x100000000)+x9*(0xffffcd13-0x100000000)+x10*(0xffffccd0-0x100000000)+x11*(0xffff7e84-0x100000000)+x12*(0xffffbba6-0x100000000)+x13*0x2e48+x14*(0xffffa9f0-0x100000000)+x15*0x2c1c+x16*0xf079==4208148)


f.add(x1*(0xfffff185-0x100000000)+x2*0xca8b+x3*0x3f8c+x4*0x875c+x5*0x4e6a+x6*(0xffff3318-0x100000000)+x7*(0xffff3e8e-0x100000000)+x8*(0xffffea44-0x100000000)+x9*(0xffffcdc2-0x100000000)+x10*(0xffffceec-0x100000000)+x11*(0xffff4d38-0x100000000)+x12*(0xffffe68a-0x100000000)+x13*0xe7f0+x14*(0xffffc373-0x100000000)+x15*0x2c77+x16*0x3c6a==-5405833)

print 0xffffac86-0x100000000
print f.check()
print f.model()

解答出来的结果再到check1中去逆,在IDA中跑脚本即可

a=[205,46,90,169,220,165,116,27,177,197,73,49,61,245,191,142]
b=[]
flag=''
addr=0x602480
for i in range(128*4):
    b.append(Byte(addr+i*4))
for i in a:
    flag+=chr(b.index(i))
print flag

总结

这题对我来说比较麻烦的点是Z3处理的数据非常多,我没有一个自动化脚本来处理数据。应该尝试编写脚本来处理这么多数据的。待办


RE5

题目逻辑也非常简单,输入之后check,但是跟进check函数之后无法静态观察,量太大。所以只好动态调试。

1557710544752

动态调试的过程中,发现check函数很麻烦,跳来跳去而且不是一位一位验证,但是总结起来发现,想要完整的约束 只需要对同一个字符进行8次shr ,and, cmp 来确定8个bit的具体值。那也就跟其他的流程无关了,只需要一个一个看即可。

在OD中进入check函数,只需要在check函数里不断搜索想要的指令,从shr 0找到shr 7,比如针对flag[0x2b]就搜索如下。搜索到后首先将该指令写为nop,然后将EIP设为此处跟进。最终可以确定所有字符

1557710770030

总结

方法很笨,尝试用angr来跑,但是报错了,主要是刚接触软件,还不会利用,流下了没技术的泪水。后续要学习angr这类对我来说高级一点的工具了。

最近计划

复习! 考试!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值