2023年春秋杯网络安全联赛春季赛 RE复盘(部分待补)

目录

sum

Pytrans

BWBA

Poisoned_tea_CHELL

第一种找程序加密函数的方法

第二种找程序加密函数的方法

解密


这次的春季赛仍是被打爆了,re只做出了一题,发现自己还是太菜了,好在在后期复盘中又收获了许多新知识了,不亏。

sum

获取题目附件,64位,无壳。

 用IDA对程序进行反编译,找到关键的main函数。

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char *v3; // rbp
  int v4; // r14d
  unsigned int v5; // r12d
  __int64 i; // rbx
  char v7; // al
  int v8; // eax
  const char *v9; // rax

  v3 = &matrix;
  v4 = 1;
  v5 = 0;
  puts("Welcome to Solver!");
  do
  {
    for ( i = 0LL; i != 9; ++i )
    {
      if ( !v3[i] )
      {
        v7 = getchar();
        if ( (v7 - 49) > 8u )
          v4 = 0;
        else
          v3[i] = v7 - 48;
      }
      v8 = v3[i];
      v5 += v8;
    }
    v3 += 9;
  }
  while ( v3 != &matrix + 81 );
  if ( v4 && verify("Welcome to Solver!", argv) )
  {
    puts("You Win!");
    __snprintf_chk(buf, 32LL, 1LL, 32LL, "%d", v5);
    v9 = str2md5(buf, strlen(buf));
    __printf_chk(1LL, "flag is: flag{%s}\n\n", v9);
    exit(0);
  }
  puts("Again~");
  return 0;
}

v7是来获取输入内容的,matrix中存放着一些值,长度为81,一开始以为是一个9*9的迷宫题,但发现matrix中存放的不只有0和1,还有一些其他值,不像是迷宫题。

 用Chatgpt帮忙辅助分析了一下,才知道这是一个九宫格数独游戏。

 因此,明白了matrix中存放的是九宫格中已知的值,写脚本dump出数独:

maze = [5, 3, 0, 0, 7, 0, 0, 0, 0, 6, 0, 0, 1, 9, 5, 0, 0, 0, 0, 9, 8, 0, 0, 0, 0, 6, 0, 8, 0, 0, 0, 6, 0, 0, 0, 3, 4, 0, 0, 8, 0, 3, 0, 0, 1, 7, 0, 0, 0, 2, 0, 0, 0, 6, 0, 6, 0, 0, 0, 0, 2, 8, 0, 0, 0, 0, 4, 1, 9, 0, 0, 5, 0, 0, 0, 0, 8, 0, 0, 7, 9]

for i in range(0,len(maze)):
    if i % 9 == 0:
        print('\n')
    print(maze[i],end=" ")
5 3 0 0 7 0 0 0 0 

6 0 0 1 9 5 0 0 0 

0 9 8 0 0 0 0 6 0 

8 0 0 0 6 0 0 0 3 

4 0 0 8 0 3 0 0 1 

7 0 0 0 2 0 0 0 6

0 6 0 0 0 0 2 8 0

0 0 0 4 1 9 0 0 5

0 0 0 0 8 0 0 7 9 

数独中的0就是需要填的位置,找到一个在线解数独的网站在线数独求解器 (gwalker.cn)

 这里想吐槽一下自己太粗心了,把绿色块当成是解出来的值,实际白色块才是解出来的。

468912723481342575971422657913948591537428763345261

 接着将解出的值输入到程序中即可拿到flag。

 FLAG:flag{bbcbff5c1f1ded46c25d28119a85c6c2}

Pytrans

获取题目文件,64位,无壳。

 根据题目介绍猜测是用python编写的程序,所以可以直接用pyinstxtractor转成pyc文件,再用uncompyle6转成py文件。

# uncompyle6 version 3.9.0
# Python bytecode version base 3.8.0 (3413)
# Decompiled from: Python 3.9.6 (tags/v3.9.6:db3ff76, Jun 28 2021, 15:26:21) [MSC v.1929 64 bit (AMD64)]
# Embedded file name: run.py
import base64, zlib, ctypes
try:
    mylib = ctypes.cdll.LoadLibrary('./mylib.so')
except:
    print('file no exit!')
else:
    a = []
try:
    sstr = input("Please enter the 10 digits and ending with '\\n': ").split(' ')
    if len(sstr) == 10:
        for i in sstr:
            a.append(int(i))

    mylib.check.argtypes = (
     ctypes.POINTER(ctypes.c_int), ctypes.c_int)
    mylib.check.restype = ctypes.c_char_p
    scrambled_code_string = mylib.check((ctypes.c_int * len(a))(*a), len(a))
    try:
        decoded_data = base64.b64decode(scrambled_code_string)
        uncompressed_data = zlib.decompress(decoded_data)
        exec(__import__('marshal').loads(uncompressed_data))
    except:
        print('Incorrect input caused decryption failure!')

except:
    pass
# okay decompiling run.pyc

 可以看见程序调用了一个mylib.so库,从pyinstxtractor导出的文件中找到mylib.so库。

 放入IDA中进行分析,找到check函数。

void *__fastcall check(_DWORD *x)
{
  void *v2; // [rsp+18h] [rbp-28h]
  char v3[24]; // [rsp+20h] [rbp-20h] BYREF
  unsigned __int64 v4; // [rsp+38h] [rbp-8h]

  v4 = __readfsqword(0x28u);
  sub_1239();
  if ( -27 * x[7] + -11 * x[6] + 16 * x[5] + *x + 2 * x[1] - x[2] + 8 * x[3] - 14 * x[4] + 26 * x[8] + 17 * x[9] != 14462
    || -30 * x[8] + 13 * x[5] + x[3] + x[1] + 2 * *x - 15 * x[4] - 24 * x[6] + 16 * x[7] + 36 * x[9] != -2591
    || 16 * x[6] + -21 * x[5] + 7 * x[3] + 3 * x[1] - *x - x[2] + 12 * x[4] - 23 * x[7] + 25 * x[8] - 18 * x[9] != 2517
    || -6 * x[6] + 2 * x[2] - x[1] + 2 * x[5] + 9 * x[7] + 2 * x[8] - 5 * x[9] != 203
    || -5 * x[8] + 6 * x[7] + 3 * x[1] - x[3] - x[5] + x[6] + 5 * x[9] != 3547
    || -9 * x[8] + x[4] + x[2] + x[7] - 5 * x[9] != -7609
    || 2 * x[5] + -x[3] - x[4] + x[8] + 6 * x[9] != 4884
    || x[6] - x[7] + 2 * x[8] != 1618
    || x[4] - x[6] + 2 * x[9] != 1096
    || x[8] + x[4] + x[3] + x[2] + x[1] + *x - x[5] - x[6] - x[7] - x[9] != 711
    || 2 * (2 * x[4] + x[3]) + 5 * x[5] != 7151 )
  {
    return 0LL;
  }
  v3[0] = 0;
  v3[1] = 0;
  v3[2] = 0;
  v3[3] = 0;
  v3[4] = 0;
  v3[5] = 0;
  v3[6] = 0;
  v3[7] = 0;
  v3[8] = 0;
  v3[9] = 0;
  v3[10] = 0;
  v3[11] = 0;
  v3[12] = 0;
  v3[13] = 0;
  v3[14] = 0;
  v3[15] = x[4] % 255;
  v2 = malloc(0x4F0uLL);
  sub_27E4(&unk_62C0, v2, v3);
  return v2;
}

 这里对输入值进行了比较,可以用z3进行求解来得出正确的输入值,脚本如下:

from z3 import *
def main():
    x = [BitVec("x%d"%i,16)for i in range(10)]
    s = Solver()
    s.add( -27 * x[7] + -11 * x[6] + 16 * x[5] + x[0] + 2 * x[1] - x[2] + 8 * x[3] - 14 * x[4] + 26 * x[8] + 17 * x[9] == 14462)
    s.add( -30 * x[8] + 13 * x[5] + x[3] + x[1] + 2 * x[0] - 15 * x[4] - 24 * x[6] + 16 * x[7] + 36 * x[9] == -2591)
    s.add( 16 * x[6] + -21 * x[5] + 7 * x[3] + 3 * x[1] - x[0] - x[2] + 12 * x[4] - 23 * x[7] + 25 * x[8] - 18 * x[9] == 2517)    
    s.add( -6 * x[6] + 2 * x[2] - x[1] + 2 * x[5] + 9 * x[7] + 2 * x[8] - 5 *
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值