SICNUCTF RSA逆向

SICNUCTF RSA逆向

分析主程序

int main_0()
{
  int result; // eax
  char input_in; // [esp+4Ch] [ebp-F0h]
  char v2; // [esp+4Dh] [ebp-EFh]
  int v3; // [esp+68h] [ebp-D4h]
  char v4; // [esp+6Ch] [ebp-D0h]
  char v5; // [esp+6Dh] [ebp-CFh]
  char v6; // [esp+9Dh] [ebp-9Fh]
  char v7; // [esp+A0h] [ebp-9Ch]
  char v8; // [esp+A1h] [ebp-9Bh]
  char v9; // [esp+D1h] [ebp-6Bh]
  char v10; // [esp+D4h] [ebp-68h]
  char v11; // [esp+D5h] [ebp-67h]
  char v12; // [esp+105h] [ebp-37h]
  char input; // [esp+108h] [ebp-34h]
  char v14; // [esp+109h] [ebp-33h]
  int v15; // [esp+125h] [ebp-17h]
  char v16; // [esp+139h] [ebp-3h]

  input = 0;
  memset(&v14, 0, 0x30u);
  v16 = 0;
  v10 = 0;
  memset(&v11, 0, 0x30u);
  v12 = 0;
  v7 = 0;
  memset(&v8, 0, 0x30u);
  v9 = 0;
  v4 = 0;
  memset(&v5, 0, 0x30u);
  v6 = 0;
  v3 = 0;
  printf("Welcome to 8th SICNUCTF!\nPlz input : ");
  scanf("%s", &input);
  if ( strlen(&input) == 30 && !memcmp("sicnuctf{", &input, 9u) && (unsigned __int8)v15 == 125 )
  {
    input_in = 0;
    memset(&v2, 0, 0x18u);
    sub_401023((int)&input, &input_in);
    v3 = sub_40100A((int)&input_in);
    if ( v3 == 66 )
      sub_401005((int)off_432A34[0], (int)&v4);
    else
      sub_401005((int)off_432A38, (int)&v4);
    printf("%s\n", &v4);
    result = 0;
  }
  else
  {
    sub_401005((int)off_432A38, (int)&v4);
    printf("%s\n", &v4);
    result = 0;
  }
  return result;
}

首先拿到题目要求你输入长度位30,且必须为sicnuctf{}所包裹,继续向下分析401023处函数是将中间的20个字符拷贝到另一个地址,之后就是较为关键的40100A函数了,进入该函数分析

int __cdecl sub_401680(int input_in)
{
  int v2; // [esp+4Ch] [ebp-150h]
  int i; // [esp+50h] [ebp-14Ch]
  int v4; // [esp+54h] [ebp-148h]
  char v5; // [esp+58h] [ebp-144h]
  int v6; // [esp+11Ch] [ebp-80h]
  _DWORD *v7; // [esp+120h] [ebp-7Ch]
  int v8; // [esp+124h] [ebp-78h]
  int *v9; // [esp+128h] [ebp-74h]
  int v10; // [esp+12Ch] [ebp-70h]
  int v11; // [esp+130h] [ebp-6Ch]
  char v12; // [esp+134h] [ebp-68h]
  char v13; // [esp+135h] [ebp-67h]
  char v14; // [esp+165h] [ebp-37h]
  char encode_input; // [esp+168h] [ebp-34h]
  char v16; // [esp+169h] [ebp-33h]
  char v17; // [esp+199h] [ebp-3h]

  encode_input = 0;
  memset(&v16, 0, 0x30u);
  v17 = 0;
  v12 = 0;
  memset(&v13, 0, 0x30u);
  v14 = 0;
  v10 = sub_4025A0(400, 0x10u);
  v9 = (int *)sub_402350(0);
  v8 = sub_402350(0);
  v7 = (_DWORD *)sub_402350(1);
  v6 = sub_402350(233);
  *(_DWORD *)(v10 + 564) = 16;
  v4 = 0;
  memset(&v5, 0, 0xC4u);
  v2 = sub_40101E(100, (int)&v4);
  for ( i = 0; i < v2; ++i )
    sub_405970((int)v7, *(&v4 + i), v7);
  sub_401005(input_in, (int)&encode_input);
  sub_405E10(15, &encode_input, v9);
  sub_4046E0((int)v9, v6, (int)v7, v8);
  if ( *(_DWORD *)v8 <= 2u )
  {
    v11 = **(_DWORD **)(v8 + 4);
  }
  else
  {
    sub_401005((int)off_432A38, (int)&v12);
    v11 = 0;
  }
  sub_402CA0(v9);
  sub_402CA0(v8);
  sub_402CA0(v7);
  sub_402CA0(v6);
  sub_402CC0();
  return v11;
}
变种base64

与输入有关的函数为函数401005,进入该函数

signed int __cdecl sub_401110(int input_in, int a2)
{
  signed int v3; // [esp+4Ch] [ebp-18h]
  unsigned __int8 v4; // [esp+50h] [ebp-14h]
  int v5; // [esp+54h] [ebp-10h]
  int v6; // [esp+58h] [ebp-Ch]
  int v7; // [esp+5Ch] [ebp-8h]
  int v8; // [esp+60h] [ebp-4h]

  v3 = 3;
  sub_40100F();
  v8 = 0;
  v5 = 0;
  v6 = 0;
  v7 = 0;
  while ( *(_BYTE *)(v7 + input_in) )
  {
    v4 = byte_436B58[*(unsigned __int8 *)(v7++ + input_in)];// 取映射
    if ( v4 == 0xFF )
      return -1;
    if ( v4 != 0xFD )
    {
      if ( v4 == 0xFE )
      {
        v4 = 0;
        --v3;
      }
      v8 = v4 | (v8 << 6);
      if ( ++v6 == 4 )                          // 以4个为一组
      {
        *(_BYTE *)(v5++ + a2) = BYTE2(v8);
        if ( v3 > 1 )
          *(_BYTE *)(v5++ + a2) = BYTE1(v8);
        if ( v3 > 2 )
          *(_BYTE *)(v5++ + a2) = v8;
        v8 = 0;
        v6 = 0;
      }
    }
  }
  return v5;
}

该函数将输入的函数ASCII码作为436B58处的值将其重新生成一个值,并且新值以4个为一组每个取其6位重新合并成一个24位的数字,之后又把数字拆成3组。感觉有点像base64解密。

看看436B58处有啥

在这里插入图片描述

我们可以正常输入的字符为

*0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz

正好64位。。。而且偏移取的字符最大为3F。。。。

可以判断这是一个变种的base64解密 字母表被替换,将字母表整理一下

a=[0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3A,0xFF,0xFF,0xFF,0xFF,0xFF,0x06,0x3E,0x1D,0x24,0x05,0x25,0x07,0x26,0x3C,0x3D,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF
,0xFF,0x0C,0x15,0x16,0x17,0x1A,0x1B,0x30,0x08,0x31,0x32,0x33,0x18,0x19,0x0A,0x2A,0x1E,0x1F,0x2F,0x0F,0x10,0x09,0x11,0x0D,0x0E,0x0B,0x27,0xFF,0xFF,0xFF,0xFF,0x1C
,0xFF,0x28,0x29,0x02,0x12,0x13,0x14,0x34,0x35,0x01,0x36,0x37,0x38,0x39,0x03,0x3F,0x3B,0x20,0x21,0x00,0x22,0x04,0x23,0x2B,0x2C,0x2D,0x2E,0xFF,0xFF,0xFF,0xFF,0xFF
,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF]
c=''
for x in range (0,64):
    b=a.index(x)
    c+=chr(b)
print c

打印出字母表如下

sicnu406HUNYAWXSTVdefBCDLMEF_2PQqrtv357ZabOwxyzRGIJKghjklm*p891o

继续向下分析main函数的405E10,由于函数比较长,查看运算结果发现是将字符变成了大数

再继续看函数main函数的4046E0,函数更长,于是放到PEID的插件查一下他的加密。

在这里插入图片描述

一个是mirvar(大数计算)还有一个powmod且powmod函数的地址就是4046E0,很容易想到这是RSA,放入IDA中查看一下powmod函数的参数。
在这里插入图片描述

第一个参数意义不明。。

在这里插入图片描述
第二个参数为DE04A372DD8B9DE12E25C098D58813 一串很长的数字应该是n,用python打印出10进制

前往网站进行分解整数

在这里插入图片描述

分解出100以内的质数

在这里插入图片描述
第三个参数可能就是E9了。

在这里插入图片描述

第四个参数是输入测试数据的base64解密的结果

一切都已经明了于是开始RSA解密

解密流程如下

RSA解密

在这里插入图片描述

base64变种加密
import base64
base='\x4c\x03\x4D\xb4\xa7\xcc\x8a\xe9\x85\xe4\x63\x4c\xf1\x40\xbb'
jiemi=base64.b64encode(base)
base64_table='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
base64_table2='sicnu406HUNYAWXSTVdefBCDLMEF_2PQqrtv357ZabOwxyzRGIJKghjklm*p891o'
flag=''
for x in range(0,20):
    index=base64_table.find(jiemi[x:x+1])
    flag+=base64_table2[index:index+1]
print flag

最终flag为

sicnuctf{esWWyNQAtz74m0WA8fcp}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值