zsky 发表于 2021-11-9 10:43

陇原战"疫"2021网络安全大赛_部分RE_WP

本帖最后由 zsky 于 2021-11-17 18:56 编辑

# 陇原战"疫"2021网络安全大赛_RE_WP

## EasyRe

IDA打开分析



发现`sub_4111406`这个函数是对输入的flag进行加密,然后将加密后的数据存放到`0X41A14C`中

来到`sub_4111406`函数,并不能F5, 直接动态调试一直跟




发现程序在不断的生成一些数据,长度是32





多次调试,不同输入,这里获取的数据是一样的






分析,还原算法

```cpp
#include <stdio.h>
#include <windows.h>

DWORD * enc(char* flag, char* key)
{
      DWORD* pdw_flag = (DWORD*)flag;
      DWORD* pdw_key = (DWORD*)key;

      for (int i = 0; i < 8; i++)
      {
                pdw_flag ^= pdw_key[(7 * i + 2) % 8];
      }

      for (int i = 0; i < 8; i++)
      {
                pdw_flag ^= pdw_flag << 7;
                pdw_flag ^= pdw_key[(7 * i + 3) % 8];
                pdw_flag ^= pdw_flag[(5 * i + 3) % 8];
                pdw_flag ^= pdw_flag << 13;
                pdw_flag ^= pdw_key[(7 * i + 5) % 8];
                pdw_flag ^= pdw_flag << 17;
      }
      return pdw_flag;
}


int main()
{
      char flag ="12345678901234567890123456789012";
      
      char key = { 12, 21, 30, 39, 32, 41, 50, 59, 68, 77, 86,95,88,97, 106, 115, 124, 133, 142, 151, 144, 153, 162, 171, 180, 189, 198, 207, 200, 209, 218, 227};
      enc(flag, key);
      return 0;//在这里下断点观察加密后的数据是否与IDA调试时生成的一样
}
```

在末尾下断点调试



IDA调试运行下断点观察加密后的数据



发现是一样的,还原加密算法成功,现在开始写解密脚本

```cpp
#include <stdio.h>
#include <windows.h>

VOID dec_shift_xor(DWORD* mingwen, int shiftlen) {
      //pdw_flag ^= pdw_flag << 13类似这种加密方式,知道加密后的,解密得到原来的数据
      //mingwen指向明文
      //shiftlen指向移位的的位数

      DWORD data = *mingwen;
      DWORD mask = 1;
      for (int i = 0; i < shiftlen - 1; i++) { // 构造mask
                mask = (mask << 1) + 1;
      }

      DWORD zuidi2wei = data & mask;

      int count = 32 / shiftlen;
      count = 32 % shiftlen == 0 ? count : count + 1;
      for (int i = 0; i < count; i++)
      {
                zuidi2wei <<= shiftlen;
                mask <<= shiftlen;
                data ^= zuidi2wei;
                zuidi2wei = data & mask;
      }

      *mingwen = data;
}


DWORD* dec(char* enc_flag, char* key)
{
      DWORD* pdw_flag = (DWORD*)enc_flag;
      DWORD* pdw_key = (DWORD*)key;

      for (int i = 7; i >=0; i--)
      {
                dec_shift_xor(&pdw_flag, 17);
                pdw_flag ^= pdw_key[(7 * i + 5) % 8];
                dec_shift_xor(&pdw_flag, 13);
                pdw_flag ^= pdw_flag[(5 * i + 3) % 8];
                pdw_flag ^= pdw_key[(7 * i + 3) % 8];
                dec_shift_xor(&pdw_flag, 7);
      }

      for (int i = 0; i < 8; i++)
      {
                pdw_flag ^= pdw_key[(7 * i + 2) % 8];
      }

      return pdw_flag;
}


int main()
{
      char key = { 12, 21, 30, 39, 32, 41, 50, 59, 68, 77, 86,95,88,97, 106, 115, 124, 133, 142, 151, 144, 153, 162, 171, 180, 189, 198, 207, 200, 209, 218, 227};
      char enc_flag = { 0x15, 0x86, 0x0F, 0xF9, 0x3D, 0x7C, 0x82, 0xC8, 0x63, 0x32,0xD7, 0x1B, 0x54, 0x74, 0x0C, 0xA9, 0x05, 0x4E, 0x3F, 0x7D,0x19, 0xBC, 0xE4, 0x53, 0x7F, 0x39, 0x5B, 0xA8, 0x5E, 0xA4,0xB2, 0xD4,0}; //提取的0X41A058处的数据
      dec(enc_flag, key);
      printf("%s", enc_flag);
      return 0;
}
```

得到 `fc5e038d38a57032085441e7fe7010b0`,加上 flag{} 得到 `flag{fc5e038d38a57032085441e7fe7010b0}`

## EasyRe_Revenge

此题与EasyRe_Revenge一样,只是把密文换了,替换上图中的enc_flag即可

```
char enc_flag = { 66, 176, 232, 238, 108, 238, 208,87,50,75, 245, 243, 214, 183, 240, 211, 137, 195,97,10,64, 186, 199,56,44, 158,61,12, 132, 146,74, 214,0 };
```

后来发现,原来EasyRe那道题目,flag直接存在字符串中了,所以把密文换了,才有了这个EasyRe_Revenge

## findme

IDA打开分析





来到 403844 这个位置




很显然这个位置不可能是strcmp,观察发现404840那个地址处还存了个函数的地址 `sub_401866`,估计程序有地方把403844这个地方的地址给替换掉了

来到401866位置



分析401767函数,发现是明显的RC4加密

随便输入一个假的flag,12345678901234567890123456, 然后断下,看加密后的数据



写脚本得到密钥流

```python
fake_flag = "12345678901234567890123456"
enc_fake_flag = [0xD5, 0x25, 0xE2, 0xB6, 0xF1, 0x99, 0x4B, 0xD4, 0xB5, 0x1B,
0x81, 0xD0, 0x47, 0x8F, 0xEF, 0x35, 0x05, 0x46, 0x48, 0xEB,
0x8C, 0x21, 0x6C, 0xB8, 0x05, 0x8D]

key = ) ^ enc_fake_flag for i in range(26)]
print(key)
#
```

然后提取出`dword_403040`解密即可

```python
enc =
key =
flag = & 0XFF) ^ key) for i in range(26)]
print("".join(flag))
# SETCTF{Th1s_i5_E2_5tRcm9!}
```

## power

拿到题目,附件是ARM汇编源文件

直接用`arm-none-eabi-as.exe power`编译下生成`a.out`

IDA打开




发现是AES加密,这里写的是CBC模式,但其实是ECB模式,写脚本解密即可

```python
from Crypto.Cipher import AES
import base64
import binascii


class Aescrypt():
    def __init__(self, key, model, iv):
      self.key = self.add_16(key)
      self.model = model
      self.iv = iv

    def add_16(self, par):
      if type(par) == str:
            par = par.encode()
      while len(par) % 16 != 0:
            par += b'\x00'
      return par

    def aesencrypt(self, text):
      text = self.add_16(text)
      if self.model == AES.MODE_CBC:
            self.aes = AES.new(self.key, self.model, self.iv)
      elif self.model == AES.MODE_ECB:
            self.aes = AES.new(self.key, self.model)
      self.encrypt_text = self.aes.encrypt(text)
      return self.encrypt_text

    def aesdecrypt(self, text):
      if self.model == AES.MODE_CBC:
            self.aes = AES.new(self.key, self.model, self.iv)
      elif self.model == AES.MODE_ECB:
            self.aes = AES.new(self.key, self.model)
      self.decrypt_text = self.aes.decrypt(text)
      self.decrypt_text = self.decrypt_text.strip(b"\x00")
      return self.decrypt_text


if __name__ == '__main__':
    passwd = b"this_is_a_key!!!"
    enc_flag_str = "1030a9254d44937bed312da03d2db9adbec5762c2eca7b5853e489d2a140427b"
    enc_flag = binascii.unhexlify(enc_flag_str)

    aescryptor = Aescrypt(passwd, AES.MODE_ECB, None)# ECB
    text = aescryptor.aesdecrypt(enc_flag)
    print("明文:", text)
   
    # 明文: b'flag{y0u_found_the_aes_12113112}'
```

## Eat_something

核心代码在`Eat_something.wasm`中




找到工具将wasm转为.o文件https://www.52pojie.cn/thread-1438499-1-1.html

用IDA打开,找到`w2c_checkright`函数,这是验证flag的地方



核心算法就是这一句` v13 != (i32_load(w2c_memory, v16 + 12LL) ^ (2 * v10))`

翻译下就是`enc!= i ^ (flag * 2)`






将enc提取出来,写脚本即可

```python
enc =   [0x86, 0x8B, 0xAA, 0x85, 0xAC, 0x89, 0xF0, 0xAF, 0xD8, 0x69,
0xD6, 0xDD, 0xB2, 0xBF, 0x6E, 0xE5, 0xAE, 0x99, 0xCC, 0xD5,
0xBC, 0x8B, 0xF2, 0x7D, 0x7A, 0xE3, 0x59, 0x6F, 0x75, 0x20,
0x61, 0x72, 0x65, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x21,
0x00, 0x59, 0x6F, 0x75, 0x20, 0x61, 0x72, 0x65, 0x20, 0x77,
0x72, 0x6F, 0x6E, 0x67, 0x21, 0x00]

flag= []
for i in range(26):
    flag .append(chr((i ^ enc) // 2))
print("".join(flag))
# CETCTF{Th0nk_Y0u_DocTOr51}
```

最后将CETCTF 改为 SETCTF即为flag

zsky 发表于 2021-11-29 12:41

SiegfriedSteven 发表于 2021-11-29 01:47
大佬,我用的ida版本可能不对,出不来main函数,这是为什么呢?pdb没有识别出新版编译器写的指令?

之后 ...

你说的哪个题这是,时间太过久远,我忘的差不多了,堆栈不平衡得手动的恢复才行,你改下函数参数个数试试

Hmily 发表于 2021-11-17 18:14

@zsky 另外我还发现一个严重问题,你的图片上传全部有问题,不能用这种方式,你看下我在md发帖窗口写的话:

提示
1、每次使用Markdown代码发帖的时候,务必点击一下菜单位置的“MD”插件按钮,这样插件才能被动处理和原来编辑器冲突的问题。
2、关于图片上传编辑,可以使用论坛原有的图片上传功能,上传后通过Discuz原有贴图方法贴到MD正文中即可,不需要使用MD的图片引用语句“![]()”,戳 “演示方法”。
3、C的代码格式不能写成```c++,需要写成```cpp。
4、不支持颜色代码,因为论坛没有开启html支持,Markdown使用中有什么建议和问题欢迎在站务区发帖交流。


你需要把图片上传本地然后,用discuz的方式去贴图,你现在的方式很快缓存失效就没了。方法:https://www.52pojie.cn/misc.php?mod=faq&action=faq&id=29&messageid=36

搜索曾经的回忆 发表于 2021-11-9 10:59

那道java怎么看啊,虽然蒙出来了,但是大部分代码都看不懂

zsky 发表于 2021-11-9 12:04

本帖最后由 zsky 于 2021-11-9 12:29 编辑

终于编辑好了:'(weeqw    MD编辑的时候 ```C++ 改为```才可,否则# include <stdio.h> 直接给你当标题了。。。

Allen666 发表于 2021-11-9 14:20

好用,感谢

qe13323 发表于 2021-11-9 15:31

向大佬献上膝盖

nine5even 发表于 2021-11-9 18:07

好大哥,收藏了

flowingcity 发表于 2021-11-9 19:50

给大佬递茶,看别人都是直接看的,大佬是真的逆出来的

ZhangAqI° 发表于 2021-11-9 20:05


好大哥,收藏了

Anneliese 发表于 2021-11-9 20:06

卧槽 大佬 收藏了 感谢

S11ence 发表于 2021-11-10 00:15

讲的非常详细!尤其是wasm那题,自己看一直看不明白,看了别人的wp都很粗略
页: [1] 2 3 4 5 6 7
查看完整版本: 陇原战"疫"2021网络安全大赛_部分RE_WP