Reverse(二)

反汇编理论

编程语言

  • 第一代语言:机器语言(字节码),机器语言程序常被称为二进制文件
  • 第二代语言:汇编语言,脱离机器语言的表查找方式
  • 第三代语言:引入了关键字和结构,表达能力更接近自然语言(C、java等)

反汇编

程序员使用编译器、汇编器和链接器中的一个或几个创建可执行程序,我们使用各种工具撤销汇编和编译过程就

反汇编困难

  • 编译过程中造成损失
  • 编译属于多对多操作:源程序通过不同方式转换成汇编语言,而机器语言也可经过许多不同方式转换成源程序
  • 反汇编器非常依赖于语言和库
  • 需近乎完美的反汇编能力

模糊测试

一种发现漏洞的技术,为程序生成大量不常见的输入,希望其中一个输入会在程序中造成可被检测、分析,最终可被利用的错误

1. re1

貌似画横线这两个输出是flag

image-20211113192607302.png

右键在这些变量上可以直接查看16进制转字符后的结果,很方便

image-20211113192319255.png

最开始一直在想法看aFlag和aFlagGet,找不着

网上看可以看出是输入的v7拿去和各种转换后的v5进行比较

v5经历了_mm_loadu_si128和m128i_i8的转换,最开始这个xmmword_413E34很可疑,双击进入

image-20211113221322985.png

可以看到一串16进制,点中长16进制串按下R转成字符

image-20211113221337051.png

转成字符后倒序拼接得到:DUTCTF{We1c0met0DUTCTF}

这题本来想用OD来做着,结果不太会用(lll¬ω¬)

2.game

不得不说这题真有意思,玩个小游戏,我直接做出来了,,ԾㅂԾ,, tip:12345678

image-20211113222242641.png

image-20211113224653447.png

游戏大意就是你选中一行它上面的和下面的一行若亮则灭,若灭则亮,要让所有都亮

直接IDA查看,拖到最下面看到判断部分

image-20211113223823642.png

可以看出全部亮时,进入一个sub_457AB4()的函数,双击进入查看(其实有个偷懒方法就是改条件,改成下表34567的不等于1,直接就能跳出flag)但我还是有必要学下分析代码

image-20211113223935605.png

再进入这个sub_45E940()函数

image-20211113225329880.png

几乎可以确定这些数字转换后就是flag了

分析它!

int sub_45E940()
{
  int i; // [esp+D0h] [ebp-94h]
  char v2[22]; // [esp+DCh] [ebp-88h] BYREF
  char v3[32]; // [esp+F2h] [ebp-72h] BYREF
  char v4[4]; // [esp+112h] [ebp-52h] BYREF
  char v5[64]; // [esp+120h] [ebp-44h]

  sub_45A7BE("done!!! the flag is ");
  v5[0] = 18;  v5[1] = 64;  v5[2] = 98;  v5[3] = 5;  v5[4] = 2;  v5[5] = 4;  v5[6] = 6;
  v5[7] = 3;  v5[8] = 6;  v5[9] = 48;  v5[10] = 49;  v5[11] = 65;  v5[12] = 32;
  v5[13] = 12;  v5[14] = 48;  v5[15] = 65;  v5[16] = 31;  v5[17] = 78;  v5[18] = 62;
  v5[19] = 32;  v5[20] = 49;  v5[21] = 32;  v5[22] = 1;  v5[23] = 57;  v5[24] = 96;
  v5[25] = 3;  v5[26] = 21;  v5[27] = 9;  v5[28] = 4;  v5[29] = 62;  v5[30] = 3;
  v5[31] = 5;  v5[32] = 4;  v5[33] = 1;  v5[34] = 2;  v5[35] = 3;  v5[36] = 44;
  v5[37] = 65;  v5[38] = 78;  v5[39] = 32;  v5[40] = 16;  v5[41] = 97;  v5[42] = 54;
  v5[43] = 16;  v5[44] = 44;  v5[45] = 52;  v5[46] = 32;  v5[47] = 64;  v5[48] = 89;
  v5[49] = 45;  v5[50] = 32;  v5[51] = 65;  v5[52] = 15;  v5[53] = 34;  v5[54] = 18;
  v5[55] = 16;  v5[56] = 0;
  qmemcpy(v2, "{ ", 2);
  v2[2] = 18;  v2[3] = 98;  v2[4] = 119;  v2[5] = 108;  v2[6] = 65;  v2[7] = 41;
  v2[8] = 124;  v2[9] = 80;  v2[10] = 125;  v2[11] = 38;  v2[12] = 124;  v2[13] = 111;
  v2[14] = 74;  v2[15] = 49;  v2[16] = 83;  v2[17] = 108;  v2[18] = 94;  v2[19] = 108;
  v2[20] = 84;  v2[21] = 6;
  qmemcpy(v3, "`S,yhn _uec{", 12);
  v3[12] = 127;  v3[13] = 119;  v3[14] = 96;  v3[15] = 48;  v3[16] = 107;  v3[17] = 71;
  v3[18] = 92;  v3[19] = 29;  v3[20] = 81;  v3[21] = 107;  v3[22] = 90;  v3[23] = 85;
  v3[24] = 64;  v3[25] = 12;  v3[26] = 43;  v3[27] = 76;  v3[28] = 86;  v3[29] = 13;
  v3[30] = 114;  v3[31] = 1;
  strcpy(v4, "u~");
  for ( i = 0; i < 56; ++i )
  {
    v2[i] ^= v5[i];
    v2[i] ^= 0x13u;
  }
  return sub_45A7BE("%s\n");
}

貌似v3数组没啥用,只看v2和v5 更正:v2(22个)+v3(32个)+2个(u~)和v1(56个)比较

v2和v5循环遍历相互异或,v2再和16进制的0x13即19异或

提取数据好麻烦啊

python实现上面伪代码作用

v5 = [18, 64, 98, 5, 2, 4, 6, 3, 6, 48, 49, 65, 32, 12, 48, 65, 31, 78, 62, 32, 49, 32, 1, 57, 96, 3, 21, 9, 4, 62, 3,
      5, 4, 1, 2, 3, 44, 65, 78, 32, 16, 97, 54, 16, 44, 52, 32, 64, 89, 45, 32, 65, 15, 34, 18, 16, 0]
v2 = [123, 32, 18, 98, 119, 108, 65, 41, 124, 80, 125, 38, 124, 111, 74, 49, 83, 108, 94, 108, 84, 6, 96, 83, 44, 121,
      104, 110, 32, 95, 117, 101, 99, 123, 127, 119, 96, 48, 107, 71, 92, 29, 81, 107, 90, 85, 64, 12, 43, 76, 86, 13,
      114, 1, 117, 126, 0]
for i in range(56):
    v2[i] ^= v5[i]
    v2[i] ^= 19
flag = ""
for i in v2:
      flag += chr(i)
print(flag)

得到:zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t}

学习总结

IDA使用

shift+F12可以查看字符串,alt+T查找指定字符串

最后修改:2023 年 12 月 14 日
如果觉得我的文章对你有用,请随意赞赏