zorropub 攻防世界

工具

IDA+linux(本题比较老,若用kali会报libc1.0.0丢失的错)

思路展开
0x01.查壳–>无壳+64位
0x02.IDA启动

main函数

int __fastcall main(__int64 a1, char **a2, char **a3)
{
  size_t v3; // rax
  int v5; // [rsp+1Ch] [rbp-104h]
  int v6; // [rsp+20h] [rbp-100h]
  int i; // [rsp+24h] [rbp-FCh]
  unsigned int seed; // [rsp+28h] [rbp-F8h]
  unsigned int v9; // [rsp+2Ch] [rbp-F4h]
  char v10; // [rsp+30h] [rbp-F0h]
  char v11[16]; // [rsp+90h] [rbp-90h]
  char v12[32]; // [rsp+A0h] [rbp-80h]
  char s; // [rsp+C0h] [rbp-60h]
  char s1[40]; // [rsp+E0h] [rbp-40h]
  unsigned __int64 v15; // [rsp+108h] [rbp-18h]

  v15 = __readfsqword(0x28u);
  seed = 0;
  puts("Welcome to Pub Zorro!!");
  printf("Straight to the point. How many drinks you want?", a2);
  __isoc99_scanf("%d", &v5);
  if ( v5 <= 0 )
  {
    printf("You are too drunk!! Get Out!!", &v5);
    exit(-1);
  }
  printf("OK. I need details of all the drinks. Give me %d drink ids:", (unsigned int)v5);
  for ( i = 0; i < v5; ++i )
  {
    __isoc99_scanf("%d", &v6);
    if ( v6 <= 16 || v6 > 0xFFFF )
    {
      puts("Invalid Drink Id.");
      printf("Get Out!!", &v6);
      exit(-1);
    }
    seed ^= v6;
  }
  i = seed;
  v9 = 0;
  while ( i )
  {
    ++v9;
    i &= i - 1;
  }
  if ( v9 != 10 )
  {
    puts("Looks like its a dangerous combination of drinks right there.");
    puts("Get Out, you will get yourself killed");
    exit(-1);
  }
  srand(seed);
  MD5_Init((__int64)&v10);
  for ( i = 0; i <= 29; ++i )
  {
    v9 = rand() % 1000;
    sprintf(&s, "%d", v9);
    v3 = strlen(&s);
    MD5_Update(&v10, &s, v3);                   // s里的值按照v3的长度放入v10
    v12[i] = v9 ^ LOBYTE(dword_6020C0[i]);
  }
  v12[i] = 0;
  MD5_Final((__int64)v11, (__int64)&v10);       // v10 md5后的值放入v11
  for ( i = 0; i <= 15; ++i )
    sprintf(&s1[2 * i], "%02x", (unsigned __int8)v11[i]);// 从v11[i]以16进制输出至少输出两位,不够两位补零,若多于两位则原样输出,存出在s1的位置
  if ( strcmp(s1, "5eba99aff105c9ff6a1a913e343fec67") )
  {
    puts("Try different mix, This mix is too sloppy");
    exit(-1);
  }
  return printf("\nYou choose right mix and here is your reward: The flag is nullcon{%s}\n", v12);
}

整体逻辑明朗:
输入两个数,生成随机数种子,然后生成随机数,随机数每次和LOBYTE(dword_6020C0[i])异或就是flag
随机数随机数种子——通俗易懂版
观察随机数逻辑:
从上往下看,生成的随机数md5加密赋值给v11[i],sprintf(&s1[2 * i], "%02x", (unsigned __int8)v11[i]);v11[i]按照 "%02x"取前16位传到s1[2*i]。最后s1和5eba99aff105c9ff6a1a913e343fec67 比较。

“%02x”
X 表示以十六进制形式输出
02 表示不足两位,前面补0输出;如果超过两位,则实际输出

5eba这个字符串不是随机数的md5值,原因:只取了前16位放到s1的偶数位置,奇数位置推测事先已经安排好了。
所以题目对随机数是限制型的,所以想到爆破。

0x03.爆破

利用python的一个模块:subprocess,将我们的数输入到程序中
python subprocess模块

import subprocess

a = []

for i in range(16,0xffff):
	c = 0
	j = i
	while(j):
		c = c + 1
		j = j & (j - 1)
	if(c == 10):
		a.append(i)

flag = ""

for i in a:
	proc = subprocess.Popen(['./zorropub'], stdin=subprocess.PIPE, stdout=subprocess.PIPE);
	out = proc.communicate(('1\n%s\n'%i).encode('utf-8'))[0]
	#print(out)
	if "nullcon".encode('utf-8') in out:
		print(out)
		break;

nullcon{nu11c0n_s4yz_x0r1n6_1s_4m4z1ng}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值