首页 > 其他分享 >攻防世界 Replace Reverse二星题

攻防世界 Replace Reverse二星题

时间:2024-04-03 13:34:18浏览次数:304  
标签:101 Reverse 54 57 53 Replace 二星 100 52

解题过程中,虽然解出来了,但是磕磕绊绊犯了一些错误,记录一下


 

分析过程

PE查壳

有一个upx壳,最下面给了脱壳提示: upx.exe -d Replace.exe 

 脱壳结束,丢到IDA里,SHIF+F12,查看字符串,看到一个可疑的”Well Done!\n“,点进去看看,发现就是主函数,反汇编主函数

  •  Buffer很明显是输入,且长度要<=37
  • 判断函数==1就成功,显然这就是关键

sub_401090函数(改了一点名称) 

 1 // 最后要输出1
 2 // a1是输入,a2是输入的长度且为35
 3 int __fastcall sub_401090(int a1, int a2)
 4 {
 5   int v4; // edx
 6   char char_v5; // al
 7   int high4; // esi
 8   int low4; // edi
 9   char char_v8; // al
10   int v9; // eax
11   char char_v10; // cl
12   int v11; // eax
13   int v12; // ecx
14 
15   if ( a2 != 35 )
16     return -1;
17   v4 = 0;
18   while ( 1 )
19   {
20     char_v5 = *(_BYTE *)(v4 + a1);
21     high4 = (char_v5 >> 4) % 16;                // 先右移4位,相当于把原来8位的高4位数移动到低4位,新高4位全都置零——再%16,相当于取出变换后新8位的低4位——也就是取出原来数的高4位
22     low4 = ((16 * char_v5) >> 4) % 16;          // 先*16,相当于左移4位,原来的低4位移动到高4位,新的低4位置零——再右移4位,相当于移回来了,不过高4位都是0——再%16,取出低4位——原就是取出原来数的低4位
23     char_v8 = byte_402150[2 * v4];
24     if ( char_v8 < 48 || char_v8 > 57 )
25       v9 = char_v8 - 87;
26     else
27       v9 = char_v8 - 48;
28     char_v10 = byte_402151[2 * v4];
29     v11 = 16 * v9;                              // v9*16,相当于左移4位————为后面组成新的8位做准备,作为新数的高4位
30     if ( char_v10 < 48 || char_v10 > 57 )
31       v12 = char_v10 - 87;
32     else
33       v12 = char_v10 - 48;                      // 作为新数的低4位
34     if ( (unsigned __int8)byte_4021A0[16 * high4 + low4] != ((v11 + v12) ^ 25) )// 16 * high4 + low4——操作的目的是组成新的8位数——其实就是原来输入的数
35                                                 // ((v11 + v12) ^ 25)——将上面获得v11与v12组成新的数,与25异或
36                                                 // 最后进行比较,相等才能return 1
37       break;
38     if ( ++v4 >= 35 )
39       return 1;
40   }
41   return -1;
42 }

总而言之,从byte_402150取一个元素作为char_v8,变换后获得组成高位的v11;从byte_402151取一个元素作为char_v10,变换后获得组成低位的v12,最后组成一个新的数去异或

【异或后得到的值】要与 【将输入作为下标,从byte_4021A0中取出的数】 相等

byte_402150与byte_402151

 !!在这里我就犯了一个错误,我还以为是我IDA又出现问题了....byte_402150数组的32h后面没有 0 表示结束,所以要继续往下读取,一直到出现 0 ,即byte_402150是50+byte_402151

unsigned char ida_chars[] =
{
   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, 
    0,   0,   0,   0,   0,   0,   0,   0,   0
};
unsigned char ida_chars[] =
{
   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, 
    0,   0,   0,   0,   0,   0,   0,   0,   0
};

byte_4021A0

选中全部,SHIF+E-->选中‘C unsigned char array (decimal)’,得到数组的值(上面也是这么得到的)

unsigned char ida_chars[] =
{
   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,  22
};

解题脚本(自己写的常规版本)

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

这里我犯了一个弱智错误

  • 最初写脚本的时候,想照着反汇编代码的思路去写,在后面写了一个 for j in range(len(str_data)): if str[i]==((v11 + v12) ^ 25):v4=((v11 + v12) ^ 25)
  • 结果导致运行没有报错,也没有结果
  • str[i]==((v11 + v12) ^ 25)这一行代码在每次循环中都会遍历str列表来查找是否存在相等的值,这会导致程序在执行时花费很长时间,因为它的时间复杂度是 O(n),其中 n 是str列表的长度。由于列表长度非常大,因此这种线性搜索的方法会非常慢,尤其是在内层循环中还嵌套了一个循环。这也解释了为什么代码没有输出也没有报错,因为它可能需要很长时间才能完成运行

解题脚本(枚举正向爆破)

这个版本是我参考别的大佬的wp时候学到的,记录一下

由于用了取余 % 运算,所以采用枚举正向爆破的方法,让flag中的每一个字符遍历常用的字符(ascii码表中32-126),带入加密算法,如果成功,就把这个flag存入

list1=[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]
list2=[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]
list3=[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, 22, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
v4=0
flag=""
for i in range(35):
    v8=list1[2*i]
    if v8 < 48 or v8 > 57:
        v9=v8 - 87
    else:
        v9=v8 - 48
    v10=list2[2*i]
    v11=16*v9
    if v10 <48 or v10 > 57:
        v12=v10-87
    else:
        v12=v10-48
    v4=((v11+v12)^25)
    for a in range(32,127):
        v5=a
        v6=(v5>>4)%16
        v7=((16*v5)>>4)%16
        if list3[16*v6+v7] == v4:
            flag+=chr(a)
print(flag)

flag

flag{Th1s_1s_Simple_Rep1ac3_Enc0d3}

标签:101,Reverse,54,57,53,Replace,二星,100,52
From: https://www.cnblogs.com/demo41/p/18112473

相关文章

  • 羊城杯2023 | Reverse
    羊城杯2023CSGO学习到了sharpODorzIDA的话没办法动调至少很难动调FindCrypt插件可以发现有base64加密查看交叉引用在汇编代码中定位到字串.text:000000000049B144mov[rsp+0C8h+var_88],rcx.text:000000000049B149mov[r......
  • C++11标准模板(STL) 算法(std::reverse)
    定义于头文件<algorithm>算法库提供大量用途的函数(例如查找、排序、计数、操作),它们在元素范围上操作。注意范围定义为 [first,last) ,其中 last 指代要查询或修改的最后元素的后一个元素。逆转范围中的元素顺序std::reverse1)反转[first,last)范围中的元素顺序表......
  • C++ std::reverse函数
    函数原型,定义std::reverse定义于头文件 <algorithm>1(1)2template<classBidirIt>3voidreverse(BidirItfirst,BidirItlast);(C++20前)45template<classBidirIt>6constexprvoidreverse(BidirItfirst,BidirItlast);(C++20起)......
  • ARC130F Replace by average
    首先我们能够发现,最终得到的答案\(b\)一定为下凸的。但是直接求凸壳肯定不行。具体地,答案的凸壳要满足对于每个\(x\),\(b_x\)都是整数,即每段斜率都是整数。可以发现找到能包住点集,最贴合的一个这样的\(b\)数组就是答案,因为题目给定的操作让我们每次都只能扩展最贴紧的点。那......
  • hackme 【攻防世界】Reverse
    题目: 丢到PE里,无壳,64bit丢到IDA里,shift+F12,查看字符串,找到一个很可疑的字符串跟进去看看,找到目标函数,我另外搜索了一下,没有mian函数,sub_400F8E应该就是解题的关键函数有部分变量我修改的名字,为了方便理解1__int64__fastcallsub_400F8E(__int64a1,inta2,inta......
  • BABYRE 【攻防世界】 Reverse
    题目 丢进ExeinfoPE里面,得到64bit,无壳丢进IDApro(x64)里面,找到主函数 代码中有一个花指令:*(unsignedint(__fastcall**)(char*))judge)(input) unsignedint(__fastcall**)(char*):这是一个函数指针类型,指向一个接受char*类型参数并返回unsignedint类型的函......
  • AtCoder Grand Contest 022 E Median Replace
    洛谷传送门AtCoder传送门考虑对于一个确定的串怎么判断合法性。容易发现删到某个时刻若\(1\)的个数大于\(0\)的个数了,因为我们肯定不会蠢到在不是全\(1\)的时候删\(111\),所以\(c_1-c_0\)在不是全\(1\)的时候至少是不会变小的。所以我们的目标就是让\(c_1-c_0......
  • 「AGC019B」 Reverse and Compare
    题意给定一个长度为\(n\)小写英文字母组成的字符串\(s\)。可以任意选定\(1\lex\ley\len\),把\(s_x\)到\(s_y\)之间的字符翻转。求最终不同字符串的方案数。分析我们先考虑所有字符都不同的情况。小学奥数的加法原理告诉我们,每一位都不同的字符串,对于第\(i\)位,可......
  • drf源码剖析----版本、reverse
    点击查看代码classAPIView(View):defdispatch(self,request,*args,**kwargs):self.args=argsself.kwargs=kwargsrequest=self.initialize_request(request,*args,**kwargs)self.request=requestself.headers......
  • replace去除多个不同的字符
    python字符串一次替换多个字符使用replace替换多处_pythonreplace只替换第二个-CSDN博客pandas处理文本特征之特殊字符剔除_pandas删除特定字符-CSDN博客大写w表示去除特殊字符小写w表示匹配特殊字符 ......