[XCTF-Reverse] 66 nullcon-hackim-2016_pseudorandom

这题有一堆整不明白的加密函数,每次输入一个数,加密处理后如果正确就放到串里,最后这个串的md5给出了,然后再用sha1的加密后数据进行一个简单加密得到flag

没办法只能gdb一点点跟进。

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  size_t v3; // rax
  size_t v4; // rax
  const char *v5; // rsi
  char v7[48]; // [rsp+90h] [rbp-210h]
  char s1[48]; // [rsp+C0h] [rbp-1E0h]
  char v9[32]; // [rsp+F0h] [rbp-1B0h]
  char v10[28]; // [rsp+110h] [rbp-190h]
  int i; // [rsp+12Ch] [rbp-174h]
  char v12; // [rsp+130h] [rbp-170h]
  char v13; // [rsp+190h] [rbp-110h]
  char s; // [rsp+1F0h] [rbp-B0h]
  int v15; // [rsp+27Ch] [rbp-24h]
  unsigned int v16; // [rsp+280h] [rbp-20h]
  unsigned int v17; // [rsp+284h] [rbp-1Ch]
  int v18; // [rsp+288h] [rbp-18h]
  unsigned int v19; // [rsp+28Ch] [rbp-14h]
  char **v20; // [rsp+290h] [rbp-10h]
  int v21; // [rsp+298h] [rbp-8h]
  unsigned int v22; // [rsp+29Ch] [rbp-4h]

  v22 = 0;
  v21 = a1;
  v20 = a2;
  printf("I will generate some random numbers.\n", a2, a3);
  printf("If you can give me those numbers, you will be $$rewarded$$\n");
  printf("hmm..thinking...");
  fflush(stdout);
  rand();
  v19 = rand();
  v18 = 0;
  printf("OK. I am Ready. Enter Numbers.\n");
  v15 = sub_400C30(v19);
  v16 = (1 << sub_400B40(v19)) - 1;
  MD5_Init(&v13);
  SHA1_Init(&v12);
  while ( v18 != v19 )
  {
    __isoc99_scanf("%d", &v17);
    if ( !(unsigned int)sub_400EA0(v16, v17) )
      sub_400AE0();
    v16 += v17;
    sprintf(&s, "%d", v17);
    v3 = strlen(&s);
    MD5_Update(&v13, &s, v3);
    v4 = strlen(&s);
    SHA1_Update(&v12, &s, v4);
    while ( (~v15 | ~v16) != -1 )
    {
      v18 = v15 ^ v18 | v15 & v18;
      v16 &= v15 ^ v16;
      v15 = sub_400C30(v19 & (v18 ^ v19));
    }
  }
  MD5_Final(v10, &v13);
  for ( i = 0; i < 16; ++i )
    sprintf(&s1[2 * i], "%02x", (unsigned __int8)v10[i]);
  if ( strcmp(s1, (const char *)(unsigned int)"15b74b4db57d0afdfe98eb5dbc3b542b") )
    sub_400AE0();
  printf("Good Job!!\n");
  printf("Wait till I fetch your reward...");
  fflush(stdout);
  v5 = &v12;
  rand();
  SHA1_Final(v9, &v12);
  for ( i = 0; i < 20; ++i )
  {
    v5 = "%02x";
    sprintf(&v7[2 * i], "%02x", (unsigned __int8)v9[i]);
  }
  printf("OK. Here it is\n", v5);
  for ( i = 0; i < 40; ++i )
    v7[i] = (dword_6020D0[i] & 0x4A | ~LOBYTE(dword_6020D0[i]) & 0xB5) ^ (v7[i] & 0x4A | ~v7[i] & 0xB5);
  printf("The flag is:nullcon{%s}\n", v7);
  return v22;
}

先随便输入个数,然后断在0x401004,正确的值应该是$rdi-*(int *)($rbp-0xc)不过这样每次只能跟到一个数,不过可以猜,第1行头是0x8000然后是*=2,到一定值后为上一个头的一半0x4000。弄到30多个失去耐心了,看了下网上的exp,用的angr。不过这东西一直也装不上。最后一共有120多项。

不过这里在中间会报错,如果不报错的话,一次测一行,用gdb脚本,到不正确的时候停掉,每次一行应该也能完成。

from pwn import *
from hashlib import md5,sha1

dword_6020D0 = [0x0D,0x52,0x67,0x53,0x44,0x40,0x16, 0x8,
                0x51,0x67, 0x6,0x0B,0x52, 0x3, 0x0, 0x0,
                0x5F, 0x1,0x0B,0x6F,0x53,0x55,0x43,0x6A,
                0x53,0x50,0x5B, 0x5,0x51, 0x4,0x10,0x3A,
                0x1, 0x54,0x5C, 0x7,0x4E,0x41,0x9, 0x46]

v18 = [0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000, #14
       0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000, 0x4000000, 0x8000000,  #14
       0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, #12
       0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, #10
       0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 
       0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 
       0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 
       0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, #9
       0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, #9
       0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, #7
       0x20, 0x40, 0x80, 0x100,  #4
       0x10, 0x20, 0x40, 0x80,
       0x8, 0x10, 0x20, 0x40,
       0x4, 0x8, 0x10, 0x20,
       2, #1
       1]


p = process('./pseudorandom')
p.recv()
context(log_level='debug')
a = ''
for i in v18:
    print(i, hex(i))
    #p.sendline(str(i).encode())
    a +=str(i)

#p.recv()   
print(md5(a.encode()).hexdigest())
print(sha1(a.encode()).hexdigest())

'''
  for ( i = 0; i < 40; ++i )
    v8[i] = (dword_6020D0[i] & 0x4A | ~LOBYTE(dword_6020D0[i]) & 0xB5) ^ (v8[i] & 0x4A | ~v8[i] & 0xB5);
'''


v8 = sha1(a.encode()).hexdigest()
v8 = [ord(i) for i in v8]
for i in range(40):
    v8[i] = (dword_6020D0[i] & 0x4A | ~dword_6020D0[i] & 0xB5) ^ (v8[i] & 0x4A | ~v8[i] & 0xB5)
print(b'nullcon{' + bytes(v8) + b'}')
pause()

输入正确后会显示flag,后边是改成不用运行程序直接写结果的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
城市应急指挥系统是智慧城市建设的重要组成部分,旨在提高城市对突发事件的预防和处置能力。系统背景源于自然灾害和事故灾难频发,如汶川地震和日本大地震等,这些事件造成了巨大的人员伤亡和财产损失。随着城市化进程的加快,应急信息化建设面临信息资源分散、管理标准不统一等问题,需要通过统筹管理和技术创新来解决。 系统的设计思路是通过先进的技术手段,如物联网、射频识别、卫星定位等,构建一个具有强大信息感知和通信能力的网络和平台。这将促进不同部门和层次之间的信息共享、交流和整合,提高城市资源的利用效率,满足城市对各种信息的获取和使用需求。在“十二五”期间,应急信息化工作将依托这些技术,实现动态监控、风险管理、预警以及统一指挥调度。 应急指挥系统的建设目标是实现快速有效的应对各种突发事件,保障人民生命财产安全,减少社会危害和经济损失。系统将包括预测预警、模拟演练、辅助决策、态势分析等功能,以及应急值守、预案管理、GIS应用等基本应用。此外,还包括支撑平台的建设,如接警中心、视频会议、统一通信等基础设施。 系统的实施将涉及到应急网络建设、应急指挥、视频监控、卫星通信等多个方面。通过高度集成的系统,建立统一的信息接收和处理平台,实现多渠道接入和融合指挥调度。此外,还包括应急指挥中心基础平台建设、固定和移动应急指挥通信系统建设,以及应急队伍建设,确保能够迅速响应并有效处置各类突发事件。 项目的意义在于,它不仅是提升灾害监测预报水平和预警能力的重要科技支撑,也是实现预防和减轻重大灾害和事故损失的关键。通过实施城市应急指挥系统,可以加强社会管理和公共服务,构建和谐社会,为打造平安城市提供坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值