[网鼎杯 2020 青龙组]jocker

传送门:[网鼎杯 2020 青龙组]jocker

不会做呜呜,看了别人 wp 才做出来的,求师傅带带

无壳,扔进 IDA,f5 发现不能反编译,原因是堆栈不平衡,先进行栈指针修改

options->general->勾选stack pointer

快捷键 alt+k,在 call 的位置修改值改为 0

修改后长这样

f5 发现还是报错,继续修改下一个 call 的位置的值为 0

修改后如下

然后就可以顺利反汇编了,主函数如下

不是非常复杂,首先可以得到输入内容长度为 24,然后有三个关键函数 wrong(), omg(), encrypt(),分别进入看一下

首先 wrong 函数如下

是对我们的输入内容进行了一个简单的加密,先不管继续看看 omg 函数

这个函数是将加密过后的输入内容与 unk_4030C0 进行对比

把 unk_4030C0 的值搞出来,根据 wrong 函数的思路逆向写个脚本就可以得到应当输入的内容是什么

#include <bits/stdc++.h>
using namespace std;
int a[] = {102, 107, 99, 100, 127, 97, 103, 100, 59, 86, 107, 97, 123, 38, 59, 80, 99, 95, 77, 90, 113, 12, 55, 102}; 
int main() {
  for (int i = 0; i < 24; i++) {
    if (i & 1) a[i] += i;
    else a[i] ^= i;
  }
  for (int i = 0; i < 24; i++) 
    cout << (char)a[i];
  return 0;
}

得到输入内容:flag{fak3_alw35_sp_me!!},很明显是个假 flag

继续往下看第三个关键函数 encrypt(),但发现 encrpy 不能反编译

这里的 for 循环其实是把程序里加壳的部分给脱壳,所以动态调试

借助中文搜索引擎定位到主函数部分后,可以看到如下图这一部分应该对应着上面所说的 for 循环

而根据 IDA 中的代码中函数调用的位置可以得到,下面的那个 call 就是所谓的 encrypt 函数

在这里下断点执行过去,F7 单步进入,这个函数就长这样

然后 olldump 脱壳,保存到新的 exe

新程序拖入 IDA 分析,找到 start 函数,看到如下

就是将输入的内容与 aHahahahaDoYouF 进行异或(注意只异或了19个字节),然后和 unk_403040 比较,aHahahahaDoYouF 的值如下

所以搞出 unk_403040 的值并写出脚本还原一下

#include <bits/stdc++.h>
using namespace std;
int a[] = {14, 13, 9, 6, 19, 5, 88, 86, 62, 6, 12, 60, 31, 87, 20, 107, 87, 89, 13};
string s = "hahahaha_do_you_find_me?"; 
int main() {
  for (int i = 0; i < 19; i++)
    cout << (char)(s[i] ^ a[i]);
  return 0;
}

得到:flag{d07abccf8a410c

少了一部分,于是再四处瞅瞅,还能发现一个函数

这函数多少有些离谱,于是开始猜谜时刻

由于 flag 结尾一定是 "}",所以盲猜 v3 与某个数异或得到剩下的 flag

然后 v3 最后一位是 ":" 也就是 58,58 ^ '}' = 71,大胆猜测每一位都与 71 异或

#include <bits/stdc++.h>
using namespace std;
string s = "%tp&:"; 
int main() {
  for (int i = 0; i < 5; i++)
    cout << (char)(s[i] ^ 71);
  return 0;
}

得到 b37a}

拼接后得到完整 flag:flag{d07abccf8a410cb37a}

离谱

posted @ 2021-08-28 17:44  Moominn  阅读(550)  评论(2编辑  收藏  举报