DosSnake

16位汇编,无法得到伪c代码,直接看汇编

2024-07-22T01:47:23.png
写脚本解密:

#include <stdio.h>
#include <stdlib.h>
int maizymdln()
{
  char b[] = "DASCTF";
  unsigned char a[] =
      {
          63, 9, 99, 52, 50, 19, 42, 47, 42, 55,
          60, 35, 0, 46, 32, 16, 58, 39, 47, 36,
          58, 48, 117, 103, 101, 60};
  for (int i = 0; i < 32; i++)
  {
    a[i] ^= b[i % 6];
    printf("%c", a[i]);
  }
  return 0;
}

Strangeprograme:

hook过程

方法一:直接调试

假的加密过程交叉引用来到这里,一直调试能调出来是从如下选中地方进行memcmp的hook
2024-07-22T01:49:08.png
跟进函数,这个函数是进行不同函数的调度,reslut=v3()下断点,三次调试后来到关键的函数
2024-07-22T01:49:30.png
2024-07-22T01:49:36.png
sub_4111BD函数中,先是找.DASCTF段,然后解密DASCTF
2024-07-22T01:49:52.png
2024-07-22T01:50:00.png
之后过掉反调试,到下面的hook

先是找到memcmp的位置
2024-07-22T01:50:16.png
image

这里进行memcmp函数的hook,其中a2所指向的函数就是hook后的新memcmp函数
2024-07-22T01:50:32.png

方法二:附加进程调试

已经知道是hook了memcmp函数,在和假flag比较的memcmp函数那里下断点,运行程序,附加进程调试,f7跟进memcmp函数,就能找到真函数

解密

memcmp函数获取前8个字节字符串DASCTF{? 进行tea加密, for循环中前8个字节每次tea加密后的值作为key去异或加密flag后面的数据
2024-07-22T01:50:49.png
写脚本解密:

#include <stdio.h>
#include <stdint.h>
#include <string.h>
void decrypt(unsigned int *v, unsigned int *k)
{
  unsigned int v0 = v[0], v1 = v[1], sum = -0x61C88647 * 16, i;
  unsigned int k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
  for (i = 0; i < 16; i++)
  {
    sum += 0x61C88647;
    v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
    v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
  }
  v[0] = v0;
  v[1] = v1;
}

int main()
{
  __int64 v1;     // rax
  __int64 v3;     // [esp-8h] [ebp-24Ch]
  int j;          // [esp+D0h] [ebp-174h]
  size_t i;       // [esp+F4h] [ebp-150h]
  int v9;         // [esp+12Ch] [ebp-118h]
  int v10;        // [esp+130h] [ebp-114h]
  char savedregs; // [esp+244h] [ebp+0h] BYREF
  unsigned char Str[41] = {
      0xF9, 0x4D, 0x2B, 0xBC, 0x13, 0xDD, 0x13, 0x62, 0xC9, 0xFC,
      0xFF, 0x89, 0x7D, 0x4F, 0xC9, 0x0F, 0x63, 0x1D, 0x6D, 0x52,
      0x50, 0xFD, 0x41, 0xE3, 0x33, 0x76, 0x28, 0x97, 0x38, 0x36,
      0xF9, 0x6B, 0x90, 0x39, 0x14, 0x83, 0x2C, 0xE2, 0x2C, 0x1F,
      0x00

  };
  unsigned char key[16] = {0x78, 0x56, 0x34, 0x12, 0x12, 0x11, 0x10, 0x09, 0x16, 0x15,
                           0x14, 0x13, 0x18, 0x17, 0x16, 0x15};
  unsigned int *Str1 = (unsigned int *)Str;
  for (i = 2; i < 10; i += 2)
  {
    *(unsigned int *)&Str[4 * (10 - i) + 4] ^= Str1[1];
    *(unsigned int *)&Str[4 * (10 - i)] ^= Str1[0];
    decrypt(Str1, key);
  }
  decrypt(Str1, key);
  printf("%s", Str);
  return 0;
}

运行得到flag

BabyAndroid:

附件给了两个,一个是txt,存的程序返回结果,另一个就是apk,主要代码逻辑如下,

先对Sex.jpg图片进行一个rc4的解密,将解密后的数据使用InMemoryDexClassLoader加载器来加载成dex文件,调用so文件中的sentInt函数来对数据进行加密处理,再反射调用dex文件中encrypt函数进行加密,最后得到的结果返回

所以解密的思路就是:(1)从txt中拿到返回的密文(2)解密dex中的加密过程 (3) 解密so文件中对数据的加密
2024-07-22T01:51:09.png
2024-07-22T01:51:19.png

1.拿到dex文件,逆向加密过程

从asset文件夹中找到Sex.jpg图片转base64后,拿去rc4解密,密钥就是DASCTF
2024-07-22T01:51:35.png
dex文件加密过程
2024-07-22T01:51:50.png
2.逆向so文件中对数据的处理

浮点数数据在so文件的函数中处理
2024-07-22T01:52:13.png
2024-07-22T01:52:20.png
找到对浮点数的处理函数
2024-07-22T01:52:37.png2024-07-22T01:52:45.png
一维DCT变换,右边是一维DCT变换的加密过程,和离散傅里叶变换很像,但是有些不同,后面补充离散傅里叶变换

参考文章离散余弦变换:DCT离散余弦变换 | CTF of Z2BNS

写脚本解密:

import cv2
import numpy as np

# 准备输入的离散余弦变换系数矩阵
YY = np.array([458.853181,
               -18.325492,
               -18.251911,
               -2.097520,
               -21.198660,
               -22.304648,
               21.103162,
               -5.786284,
               -15.248906,
               15.329286,
               16.919499,
               -19.669045,
               30.928253,
               -37.588034,
               -16.593954,
               -5.505211,
               3.014744,
               6.553616,
               31.131491,
               16.472500,
               6.802400,
               -78.278577,
               15.280099,
               3.893073,
               56.493581,
               -34.576344,
               30.146729,
               4.445671,
               6.732204,0])

# 进行逆离散余弦变换
XX = cv2.idct(YY)

# 打印还原后的图像块
print(XX)

注意:OpenCV 库中的 cv2.idct() 方法执行逆离散余弦变换不支持奇数个数的输入数据,所以自己填充一个0就可以,运行得到flag