攻防世界WP-reverse-湖湘杯2018-Replace

17 篇文章 0 订阅
15 篇文章 0 订阅

首先查壳,upx壳,直接upx -d脱掉。
放入ida,查看伪代码,结构比较简单就不多说了。
关键是下面这个函数,return 1,则成功。

signed int __fastcall sub_401090(int a1, int a2)
{
  int v2; // ebx
  int v4; // edx
  char v5; // al
  int v6; // esi
  int v7; // edi
  char v8; // al
  int v9; // eax
  char v10; // cl
  int v11; // eax
  int v12; // ecx

  v2 = a1;//a1是输入的flag值
  if ( a2 != 35 )//a2是flag的长度
    return -1;
  v4 = 0;
  while ( 1 )
  {
    v5 = *(_BYTE *)(v4 + v2);//取flag的每一个字符,v4相当一个索引
    v6 = (v5 >> 4) % 16;
    v7 = (16 * v5 >> 4) % 16;
    v8 = byte_402150[2 * v4];
    if ( v8 < 48 || v8 > 57 )
      v9 = v8 - 87;                             // //10
    else
      v9 = v8 - 48;                             // 2
    v10 = byte_402151[2 * v4];
    v11 = 16 * v9;
    if ( v10 < 48 || v10 > 57 )
      v12 = v10 - 87;
    else
      v12 = v10 - 48;
    if ( (unsigned __int8)byte_4021A0[16 * v6 + v7] != ((v11 + v12) ^ 0x19) )
      break;
    if ( ++v4 >= 35 )
      return 1;
  }
  return -1;
}

因为题目算法中由取余运算,所以采用枚举的方法,让flag中的每一个字符遍历常用的字符(ascii码表中32-126),带入加密算法,如果成功,就把这个flag存入。
脚本

data = [50, 97, 52, 57, 102, 54, 57, 99, 51, 56, 51, 57, 53, 99, 100, 101, 57, 54, 100, 54, 100, 101, 57, 54, 100, 54, 102, 52, 101, 48, 50, 53, 52, 56, 52, 57, 53, 52, 100, 54, 49, 57, 53, 52, 52, 56, 100, 101, 102, 54, 101, 50, 100, 97, 100, 54, 55, 55, 56, 54, 101, 50, 49, 100, 53, 97, 100, 97, 101, 54, 0]
data2 = [97, 52, 57, 102, 54, 57, 99, 51, 56, 51, 57, 53, 99, 100, 101, 57, 54, 100, 54, 100, 101, 57, 54, 100, 54, 102, 52, 101, 48, 50, 53, 52, 56, 52, 57, 53, 52, 100, 54, 49, 57, 53, 52, 52, 56, 100, 101, 102, 54, 101, 50, 100, 97, 100, 54, 55, 55, 56, 54, 101, 50, 49, 100, 53, 97, 100, 97, 101, 54, 0]
compy_data = [99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187]

flag = [0 for i in range(35)]
v4=0
for i in range(35):
	for j in range(32,127):
		v5 = j
		v6 = (v5>>4)%16
		v7 = (16*v5>>4)%16
		v8=data[2*i]
		if(v8<48|v8>57):
			v9=v8-87
		else:
			v9=v8-48
		v10=data2[2*i]#这个地方开始弄错了,直接用data[2*(i+1)]是不对的
		v11 = 16*v9
		if(v10<48|v10>57):
			v12 = v10 -87
		else:
			v12 = v10 -48
		if(compy_data[16*v6+v7]==((v11+v12)^0x19)):
			flag[i] = chr(j)
			break
print("".join(flag))
print(len(flag))

还有一个错误需要记录一下,就是我用c++来写解密的时候,直接复制伪代码,compy_data 的值给了一个char类型,但是忘了写强制类型转换。因为有符号的char最大表示127,而compy_data中的值有的超过了127。
在这里插入图片描述在实际比较的过程中,有些数字会被转成“负数”
在这里插入图片描述这样再判断是否相等时肯定会出错。
总结一下,枚举,数据类型,这两个点需要注意。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值