[NewStarCTF 2023 公开赛道]easy_RE
ida 可能会把 一个数组或字符串拆开,可以通过计算地址,知道是一起的
也有的会藏在汇编窗口
Segments
IDA的Segments窗口 :shift+f7
https://www.cnblogs.com/sch01ar/p/9477697.html
ida 各种窗口也是需要看看
[翻译]The IDA Pro book 第5章---IDA DATA DISPLAY-外文翻译-看雪-安全社区|安全招聘|kanxue.com
Endian
ant=[1968519710, 2069379587, 1297621516, 2068854845, 1936406553]
key=0x12345678
for i in range(5):
ant[i]^=key
# for i in range(5):
# print(str(ant[i]))
#chr((result >> (i * 8)) & 0xFF) 提取每一字节
flag=''
for i in range(5):
flag+=''.join([chr((ant[i]>>(j*8))&0xff) for j in range(4)])
print(flag)
#flag{llittl_Endian_a
[NewStarCTF 2023 公开赛道]EzPE
这个EXE怎么运行不了呢?
去 010看看
修改后,就是正常 exe文件了。
AndroGenshin
就是一个简单的 RC4+变表base64
烦人的是,rc4工具没解出来,写脚本没有 Crypto 库,只能去虚拟机里运行。0-0
from Crypto.Cipher import ARC4
arr = [0x7D, 0xEF, 101, 0x97, 77, 0xA3, 0xA3, 110, 58, 230, 0xBA, 206, 84, 84, 0xBD, 0xC1, 30, 0x3F, 104, 0xB2, 130, 0xD3, 0xA4, 94, 75, 16, 0x20, 33, 0xC1, 0xA0, 120, 0x2F, 30, 0x7F, 0x9D, 66, 0xA3, 0xB5, 0xB1, 0x2F, 0, 0xEC, 106, 107, 0x90, 0xE7, 0xFA, 16, 36, 34, 91, 9, 0xBC, 81, 5, 0xF1, 0xEB, 3, 54, 150, 40, 0x77, 202, 150]
arrBytes = bytes(arr)
key = b"genshinimpact"
enc = ARC4.new(key)
base64_table = enc.decrypt(arrBytes)
print(base64_table)
# b'BADCFEHGJILKNMPORQTSVUXWZYbadcfehgjilknmporqtsvuxwzy1032547698/+'
import base64
str1 = "YnwgY2txbE8TRyQecyE1bE8DZWMkMiRgJW1="
string1 = "BADCFEHGJILKNMPORQTSVUXWZYbadcfehgjilknmporqtsvuxwzy1032547698/+" #替换的表
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
print (base64.b64decode(str1.translate(str.maketrans(string1,string2))))
# str.maketrans(table,result) 创建映射表,将table映射给result
# str1.translate(trans) 用 trans 映射表替换 str1
# b'flag{0h_RC4_w1th_Base64!!}'
[NewStarCTF 2023 公开赛道]C?C++?
private static void Main(string[] args)
{
int num = 35;
int[] array = new int[]
{
68,
75,
66,
72,
99,
19,
19,
78,
83,
74,
91,
86,
35,
39,
77,
85,
44,
89,
47,
92,
49,
88,
48,
91,
88,
102,
105,
51,
76,
115,
-124,
125,
79,
122,
-103
};
char[] array2 = new char[35];
int[] array3 = new int[35];
Console.Write("Input your flag: ");
string text = Console.ReadLine();
for (int i = 0; i < text.Length; i++)
{
array2[i] = text[i];
}
string text2 = "NEWSTAR";
for (int j = 0; j < num; j++)
{
char[] array4 = array2;
int num2 = j;
array4[num2] += (char)j;
char[] array5 = array2;
int num3 = j;
array5[num3] -= ' ';
}
for (int k = 0; k < 7; k++)
{
char[] array6 = array2;
int num4 = k;
array6[num4] += (char)(k ^ (int)(-(int)(text2[k] % '\u0004')));
char[] array7 = array2;
int num5 = k + 7;
array7[num5] += text2[k] % '\u0005';
char[] array8 = array2;
int num6 = k + 14;
array8[num6] += (char)(2 * k);
char[] array9 = array2;
int num7 = k + 21;
array9[num7] += (char)(k ^ 2);
char[] array10 = array2;
int num8 = k + 28;
array10[num8] += text2[k] / '\u0005' + '\n';
}
for (int l = 0; l < num; l++)
{
int num9 = (int)array2[l];
array3[l] = num9;
}
for (int m = 0; m < 35; m++)
{
bool flag = m == 34 && array3[m] == array[m];
if (flag)
{
Console.WriteLine("Right!");
}
bool flag2 = array3[m] == array[m];
if (!flag2)
{
Console.WriteLine("Wrong!");
break;
}
}
}
}
}
最开始看,觉得只要满足最后条件就行了,但发现不是,应该是要最后的,也不是每一个arrayX
都对应一步操作,要逆所有的操作
v6 = 35
j = 0
v10 = [68,75,66,72,99,19,19,78,83,74,91,86,35,39,77,85,44,89,47,92,49,88,48,91,88,102,105,51,76,115,-124,125,79,122,-103]
a2 = "NEWSTAR"
for j in range(7):
v10[j + 28] -= (ord(a2[j])//5) + 10
v10[j + 21] -= j ^ 2
v10[j + 14] -= 2 * j
v10[j + 7] -= ord(a2[j]) % 5
v10[j] -= j ^ -(ord(a2[j]) % 4)
for i in range(v6):
v10[i] -= i
v10[i] += 32
print(chr(v10[i]%256), end='')
R4ndom
一个 elf 文件,42位flag,一开始打算直接动调,但想想觉得工程有点大,要42次。并且去动调的时候,发现有反调试。先想想怎么调试:
在 main 函数开头下断点,看反调试在 main 前/后;一般就是在 init_array 里。
想到ctf一般都是伪随机,去看看有没有随机数种子。
由于设置了随机数种子,所以每次rand()
的结果都是一样的,这就是伪随机
一个反调试( ptrace),一个随机数种子
要用标准整数型,要引用库
#include <cstdint>
uint8_t enc;
#include <iostream>
#include <cstdint>
using namespace std;
int main() {
/*int enc[6];
enc[0] = 0x3513AB8AB2D7E6EELL;
enc[1] = 0x2EEDBA9CB9C97B02LL;
enc[2] = 0x16E4F8C8EEFA4FBDLL;
enc[3] = 0x383014F4983B6382LL;
enc[4] = 0xEA32360C3D843607LL;
enc[5] = 42581LL;*/
__uint8_t enc[42] = { 0xEE, 0xE6, 0xD7, 0xB2, 0x8A, 0xAB, 0x13, 0x35, 0x02, 0x7B, 0xC9, 0xB9, 0x9C, 0xBA, 0xED, 0x2E,
0xBD, 0x4F, 0xFA, 0xEE, 0xC8, 0xF8, 0xE4, 0x16, 0x82, 0x63, 0x3B, 0x98, 0xF4, 0x14, 0x30, 0x38,
0x07, 0x36, 0x84, 0x3D, 0x0C, 0x36, 0x32, 0xEA, 0x55, 0xA6 };
unsigned char Table[] =
{
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01,
0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D,
0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4,
0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7,
0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2,
0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E,
0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB,
0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB,
0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C,
0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C,
0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D,
0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A,
0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3,
0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D,
0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A,
0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E,
0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9,
0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9,
0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99,
0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
};
/*for (i = 0; i < strlen(input); ++i)
{
v3 = input[i];
v4 = rand();
input[i] = Table[(16 * ((v3 + v4 % 255) >> 4) + 15) & (v3 + v4 % 255)];
}*/
srand(0x5377654Eu);
for (int i = 0; i < 42; ++i) {
for (int j = 0; j < 256; ++j) {
if (Table[j] == enc[i]) {
printf("%c", (j - rand() % 255));
}
}
}
return 0;
}
easy_enc
第一个,类似凯撒加密
第二个,通过Key相加
第三个,按位取反
第四个,相乘
可能溢出
C 的代码都有编译器的默认类型推断影响,就是可能有(隐式)转换
可以定义 uint8_t ,或者自己去截断。
因为 input 是 char 类型,*52可能会溢出,故第四个不能逆,就只能爆破了。
#include <stdio.h>
#include <string.h>
#include <cstdint>
// 感觉比 C++好一些
int main()
{
uint8_t enc[100] = { 0xE8, 0x80, 0x84, 0x8, 0x18, 0x3C, 0x78, 0x68, 0x0, 0x70, 0x7C, 0x94, 0xC8, 0xE0, 0x10, 0xEC, 0xB4, 0xAC, 0x68, 0xA8, 0xC, 0x1C, 0x90, 0xCC, 0x54, 0x3C, 0x14, 0xDC, 0x30 };
char key[20] = "NewStarCTF";
int len = strlen(key);
uint8_t i, j;
//必须是 uint8_t 限定类型
for (i = 0; i < 29; i++) {
for (j = 32; j < 127; j++) {
uint8_t tmp = j;
//这里也是。
if (j < 'A' || j > 'Z')
{
if (j < '0' ||j > '9')
{
if (j >= 'a' && j <= 'z')
j = (j- 89) % 26 + 97;
}
else
{
j = (j - 45) % 10 + 48;
}
}
else
{
j = (j - 52) % 26 + 65;
}
j += key[i % len];
j = ~j;
j *= 52;
if (j == enc[i]) {
if ((tmp <= 'Z' && tmp >= 'A') || (tmp <= 'z' && tmp >= 'a')) {
printf("%c",tmp);
}
}
j = tmp;
}
}
return 0;
}
这么简单一个脚本,却也花了一段时间,唉!
Petals
不对,就是那个 call E8 不对,
就是下标匹配的问题
enc = [0xD0, 0xD0, 0x85, 0x85, 0x80, 0x80, 0xC5, 0x8A, 0x93, 0x89,
0x92, 0x8F, 0x87, 0x88, 0x9F, 0x8F, 0xC5, 0x84, 0xD6, 0xD1,
0xD2, 0x82, 0xD3, 0xDE, 0x87]
longth = 25
#enc = list(map(chr, enc))
v5 = []
for i in range(256):
v5.append(~(i ^ longth) & 0xff)
# 遍历 enc 并打印对应的索引
for i in range(longth):
#print(enc[i])
if enc[i] in v5:
tmp = v5.index(enc[i])
print(chr(tmp),end='')
else:
print(f"Value {enc[i]} not found in v5")
特别注意:
for 操作明确是 byte ,要 &0xff
还有就是 index()的使用
PZthon
解包,发现 python 版本是 3.8
uncompyle6只支持到py3.8
用 pycdc 或者 在线网站
代码很简单,直接秒了
AndroDbgme
放 jadx 没有什么发现,看题目名字应该是要调试
没有什么反应。
想直接在模拟器里加调试功能,结果不行,MT 有点问题
不对,最后用 MT 搞出来了,修改完 xml 文件后,保存,直接重安装。
不过这个一调试,直接就出 flag ,想知道为什么。
lazy_activtiy
要么是 data或者其他目录下藏着一个 apk 文件
或者就是存在文件里面哪里。
嗯,jeb 不好看,主要用来调试吧,还是喜欢用 jadx
不过 jeb 有一些注释还不错
两个结合用吧
嗯,这个题可以动调,也可以直接去找 editText
emmm但在我尝试动调前,AndroidKiller一把梭了
有点问题
去找一下算了
找到了。