CG-CTF simple-machine

运行一下,输入flag;
用ida打开:
1164674-20190330203844592-98247846.png
input_lengthinput_byte_804B0C0为重命名的变量;现在一个个看调用的函数。
sub_8048526():
1164674-20190330204733803-479069795.png
这个函数使用了mmap分配内存空间,并将首地址和偏移首地址0x8000的地址赋给两个变量:dword_804B160 = (int)v0;dword_804B158 = (int)(v0 + 0x8000);,其实这里就相当于一个分配栈的函数。
执行完分配栈函数之后的if判断语句中的函数调用ptrace,将自身设为被调试程序,如果程序正常执行,debugger被设置为系统。是一个用来反调试的东西,但是很容易绕过,题目也不用调试。
接着需要输入flag,长度为3的倍数。
看一下sub_8048633():

int __cdecl sub_8048633(int input_byte_804B0C0, unsigned int input_length)
{
  unsigned int v2; // eax
  int v3; // eax

  sub_8048567(dword_804B15C);                   // 0x804B158处存储mmap分配地址+0x8000地址
  dword_804B15C = dword_804B158;                // dword_804B15C = dword_804B158, 为此前的-4
  sub_8048567(dword_804B150);
  sub_8048567(dword_804B144);
  dword_804B158 -= 0x30;
  *(_DWORD *)(dword_804B15C - 0x1D) = 'deef';
  *(_DWORD *)(dword_804B15C - 0x19) = 'daed';
  *(_DWORD *)(dword_804B15C - 0x15) = 'feeb';
  *(_DWORD *)(dword_804B15C - 0x11) = 'efac';
  *(_BYTE *)(dword_804B15C - 0xD) = 0;
  for ( *(_DWORD *)(dword_804B15C - 0xC) = 0; ; ++*(_DWORD *)(dword_804B15C - 0xC) )
  {
    dword_804B140 = *(_DWORD *)(dword_804B15C - 0xC);
    if ( dword_804B140 >= input_length )
      break;
    dword_804B14C = *(_DWORD *)(dword_804B15C - 0xC);
    dword_804B140 = input_byte_804B0C0;
    dword_804B150 = dword_804B14C + input_byte_804B0C0;
    dword_804B14C = *(_DWORD *)(dword_804B15C - 0xC);
    dword_804B140 = dword_804B14C + input_byte_804B0C0;
    dword_804B140 = *(unsigned __int8 *)(dword_804B14C + input_byte_804B0C0);
    byte_804B164 = dword_804B140;
    *(_BYTE *)(dword_804B15C - 0x29) = dword_804B140;
    dword_804B144 = *(_DWORD *)(dword_804B15C - 0xC);// i
    dword_804B158 -= 0xC;
    dword_804B140 = dword_804B15C - 0x1D;
    sub_8048567(dword_804B15C - 0x1D);
    v2 = strlen(*(const char **)dword_804B158);
    dword_804B158 += 0x10;
    dword_804B148 = v2;
    dword_804B140 = dword_804B144;              // i
    dword_804B14C = 0;
    sub_80485AB(v2);
    dword_804B140 = dword_804B14C;              // i % v2
    dword_804B140 = *(unsigned __int8 *)(dword_804B14C - 0x1D + dword_804B15C);// 取array的byte
    byte_804B164 = dword_804B140;
    byte_804B164 = *(_BYTE *)(dword_804B15C - 0x29) ^ dword_804B140;// 输入与array[i%v2]异或
    *(_BYTE *)dword_804B150 = byte_804B164;     // 存于input中
    v3 = dword_804B140;
    LOBYTE(v3) = 0;
    dword_804B140 = v3 + (unsigned __int8)byte_804B164;
  }
  sub_80485A5();
  dword_804B158 = dword_804B15C - 8;
  sub_8048584(&dword_804B144);
  sub_8048584(&dword_804B150);
  return sub_8048584(&dword_804B15C);
}

sub_8048567()函数作用类似于压栈操作,并且在“栈”中压入了一个字符串“feeddeadbeefcafe”,根据代码for循环的次数为输入的字符串的长度,整个循环所做的事情就是:input_byte_804B0C0[i]=xor[i%input_length] ^ input_byte_804B0C0[i],xor为之前初始化的字符串。跳出循环之后就相当"寄存器"出栈了。
再看sub_80488C7((int)input_byte_804B0C0, (int)&unk_804B100, input_length);函数:
1164674-20190330220201533-347638070.png
函数中嵌套了两层循环,最里层跳出条件是循环次数j>=0x55555556*input_length >> 32;这应该是编译器的优化,作用相当于除3,将除法转化为乘法,0X55555556是编译器计算出来用于优化的值。
函数中ans为运算结果存放处;是由input_byte_804B0C0数组挪过来的。最终的效果相当于:ans[18*i + j] = input_byte_804B0C0[i + 3j]。数组转置了一下。
回到主函数中就是于一个已初始化的长度为54bytes的数组比较了,那么可以求出flag:

  
lst =  [  0x00, 0x03, 0x09, 0x3A, 0x05, 0x0E, 0x02, 0x16, 0x0F, 0x1F, 0x12, 0x56, 0x3B, 0x0B, 0x51, 0x50, 0x39, 0x00,  
          0x09, 0x1F, 0x50, 0x04, 0x14, 0x57, 0x3B, 0x12, 0x07, 0x3C, 0x1C, 0x3A, 0x15, 0x05, 0x0B, 0x08, 0x06, 0x01,  
          0x04, 0x12, 0x16, 0x39, 0x05, 0x0B, 0x50, 0x57, 0x09, 0x12, 0x0A, 0x27, 0x13, 0x17, 0x0E, 0x02, 0x55, 0x18 ]  
tmp = []  
xor = b'feeddeadbeefcafe'  
  
def main():  
    for i in range(18):  
        for j in range(3):  
            tmp.append(lst[i + 18*j])  
    L = len(xor)  
    for i in range(54):  
        print(chr(xor[i%L] ^ tmp[i]), end = '')  
  
if __name__ == '__main__':  
    main()

转载于:https://www.cnblogs.com/zUotTe0/p/10629383.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值