Ciscn Reverse

本文最后更新于 2024年6月5日 中午

Ciscn Reverse

更新更新博客,复现了一下国赛的四个题。

Asm_re

给了一个txt,是arm的汇编导出

分析得到如下逻辑

exp如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<stdio.h>
int main()
{
int str[]={
0x1fd7,0x21b7,0x1e47,0x2027,0x26e7,
0x10d7,0x1127,0x2007,0x11c7,0x1e47,
0x1017,0x1017,0x11f7,0x2007,0x1037,
0x1107,0x1f17,0x10d7,0x1017,0x1017,
0x1f67,0x1017,0x11c7,0x11c7,0x1017,
0x1fd7,0x1f17,0x1107,0x0f47,0x1127,
0x1037,0x1e47,0x1037,0x1fd7,0x1107,
0x1fd7,0x1107,0x2787
};

for(int i=0;i<38;i++)
{
int t=str[i]-0x1e;
t^=0x4d;
t-=0x14;
t/=0x50;
printf("%c",t);
}
return 0;
}

得到flag

flag:flag{67e9a228e45b622c2992fb5174a4f5f5}

Androidso_re

jadx打开看到主逻辑是一个DES加密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.example.re11113;
import android.util.Base64;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class inspect {
public static boolean inspect(String input_str) {
try {
byte[] input_flag = input_str.getBytes(StandardCharsets.UTF_8);
byte[] str2 = jni.getkey().getBytes(StandardCharsets.UTF_8);
Arrays.copyOf(str2, 8);
SecretKeySpec key = new SecretKeySpec(str2, "AES");
byte[] ivBytes = jni.getiv().getBytes(StandardCharsets.UTF_8);
IvParameterSpec iv = new IvParameterSpec(ivBytes);
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(1, key, iv);
byte[] encryptedBytes = cipher.doFinal(input_flag);
String encryptedFlag = Base64.encodeToString(encryptedBytes, 0).trim();
boolean bool = encryptedFlag.equals("JqslHrdvtgJrRs2QAp+FEVdwRPNLswrnykD/sZMivmjGRKUMVIC/rw==");
if(!bool) {
return true;
}
return false;
} catch (Exception exception) {
exception.printStackTrace();
return true;
}
}
}

那么我们需要获得key和iv

1
2
3
4
5
6
7
public class jni {
public static native String getiv();
public static native String getkey()
static {
System.loadLibrary("Secret_entrance");
}
}

分析得知在本地的native库里存有两个函数

apktool d app-debug.apk

一个rc4解密获得key

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from Crypto.Cipher import ARC4

def rc4_decrypt(ciphertext, key):
cipher = ARC4.new(key)
decrypted_data = cipher.decrypt(ciphertext)
return decrypted_data

key = b'YourRC4Key'

ciphertext = "TFSecret_Key".encode('utf-8')

decrypted_data = rc4_decrypt(ciphertext, key)
print(decrypted_data.decode())
#include<stdio.h>
int main()
{
int a[]={0x42,0xb1,0x66,0xdc,0x03,0x6d,0x45,0x1b};
a[0]^=0x3;
a[1]^=0x89;
a[2]^=0x33;
a[3]^=0xb8;
a[4]^=0x54;
a[5]^=0xcu;
a[6]^=0x20;
a[7]^=0x6a;
for(int i=0;i<=7;i++)
printf("%c",a[i]);
return 0;
}

key:A8UdWaeq

iv是一个rot16+base64

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import base64
def rot16_decrypt_bytes(data):
result = bytearray()
for byte in data:
if 97 <= byte <= 122:
result.append((byte - 97 + 16) % 26 + 97)
elif 65 <= byte <= 90:
result.append((byte - 65 + 16) % 26 + 65)
else:
result.append(byte)
return bytes(result)

def rot16_base64_decode(encoded_data):
rot16_decoded_bytes = rot16_decrypt_bytes(encoded_data)

base64_decoded = base64.b64decode(rot16_decoded_bytes)

return base64_decoded

encoded_text = b"F2IjBOh1mRW="
decoded_data = rot16_base64_decode(encoded_text)
if decoded_data:
print(decoded_data)

iv:Wf3DLups

有了iv和key进行DES解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from Crypto.Cipher import DES
from Crypto.Util.Padding import unpad
import base64

def des_cbc_decrypt(ciphertext_base64, key, iv):
ciphertext = base64.b64decode(ciphertext_base64)

cipher = DES.new(key, DES.MODE_CBC, iv)

decrypted_data = unpad(cipher.decrypt(ciphertext), DES.block_size)

return decrypted_data

key = b'A8UdWaeq'

iv = b'Wf3DLups'

ciphertext_base64 = 'JqslHrdvtgJrRs2QAp+FEVdwRPNLswrnykD/sZMivmjGRKUMVIC/rw=='

decrypted_data = des_cbc_decrypt(ciphertext_base64, key, iv)
print(decrypted_data.decode())

得到flag

flag:flag{188cba3a5c0fbb2250b5a2e590c391ce}

WhereThel1b

给了一个python文件和一个so文件

1
2
3
4
5
6
7
8
9
10
11
12
import whereThel1b

flag = input("where is my flag:")
flag = flag.encode()
encry = [108, 117, 72, 80, 64, 49, 99, 19, 69, 115, 94, 93, 94, 115, 71, 95, 84, 89, 56, 101, 70, 2, 84, 75, 127, 68, 103, 85, 105, 113, 80, 103, 95, 67, 81, 7, 113, 70, 47, 73, 92, 124, 93, 120, 104, 108, 106, 17, 80, 102, 101, 75, 93, 68, 121, 26]
whereThel1b.whereistheflag(flag)
ret = whereThel1b.trytry(flag)

if ret == encry:
print("rrrrrrrrrrrright")
else:
print("wwwwwwwwwwwwwwwrong")

运行后发现调用了whereThel1b

接收了一个base64加密的对象进行处理

进入so发现trytry函数调用了whereistheflag1

1
2
3
4
5
6
if ( _pyx_mstate_global_static.__pyx_d[1].ob_type != (PyTypeObject *)_pyx_dict_version_4 )
{
ModuleGlobalName = _Pyx__GetModuleGlobalName(
_pyx_mstate_global_static.__pyx_n_s_whereistheflag1,
&_pyx_dict_version_4,
&_pyx_dict_cached_value_3);

跟进查看whereistheflag1

设置了种子seed(0)然后进行的异或操作

1
v36 = PyNumber_Xor(v35, v34);

所以我们先进行异或处理再进行base64解密

exp如下

1
2
3
4
5
6
7
8
9
10
import random
import base64

encry = [108, 117, 72, 80, 64, 49, 99, 19, 69, 115, 94, 93, 94, 115, 71, 95, 84, 89, 56, 101, 70, 2, 84, 75, 127, 68, 103, 85, 105, 113, 80, 103, 95, 67, 81, 7, 113, 70, 47, 73, 92, 124, 93, 120, 104, 108, 106, 17, 80, 102, 101, 75, 93, 68, 121, 26]
random.seed(0)
for i in range(len(encry)):
encry[i] ^= random.randint(0, len(encry))
byte_data = bytes(encry)
base64_bytes=base64.b64decode(byte_data)
print(base64_bytes)

得到flag

flag:flag{7f9a2d3c-07de-11ef-be5e-cf1e88674c0b}

Gdb_debug

浏览代码发现是用随机数种子生成的两组随机数并进行的加密操作,结合题目提示动静结合可知需要动调一下,

动调之后发现随机数种子为0LL

由于随机数的随机性,我们这里写一个随机数的生成脚本进行随机数的生成并使用,

为elf文件,gcc编译生成可执行文件并运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
int main()
{
srand(time(0LL)&0xF0000000);
for(int i=0;i<=38;i++)
printf("0x%x,",rand()&0xff);
for(int l=strlen("flag{12345678901234567890123456789012}")-2;l>=0;l--)
rand();
printf("\n");
printf("\n");
for(int i=0;i<=38;i++)
printf("0x%x,",rand()&0xff);
printf("\n");
return 0;
}

观察发现需要动调去dump出ptr的值

得到ptr并进行导出

exp如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include<stdlib.h>
#include<stdio.h>
#include<memory.h>
#include<string.h>
int main()
{
const char* ciber ="congratulationstoyoucongratulationstoy";
unsigned char str[] =
{
0xBF, 0xD7, 0x2E, 0xDA, 0xEE, 0xA8, 0x1A, 0x10, 0x83, 0x73,
0xAC, 0xF1, 0x06, 0xBE, 0xAD, 0x88, 0x04, 0xD7, 0x12, 0xFE,
0xB5, 0xE2, 0x61, 0xB7, 0x3D, 0x07, 0x4A, 0xE8, 0x96, 0xA2,
0x9D, 0x4D, 0xBC, 0x81, 0x8C, 0xE9, 0x88, 0x78, 0x00
};
unsigned char v31[] =
{
0xBF, 0xD7, 0x2E, 0xDA, 0xEE, 0xA8, 0x1A, 0x10, 0x83, 0x73,
0xAC, 0xF1, 0x06, 0xBE, 0xAD, 0x88, 0x04, 0xD7, 0x12, 0xFE,
0xB5, 0xE2, 0x61, 0xB7, 0x3D, 0x07, 0x4A, 0xE8, 0x96, 0xA2,
0x9D, 0x4D, 0xBC, 0x81, 0x8C, 0xE9, 0x88, 0x78, 0x00
};
unsigned char boom1[] =
{
0xd9, 0xf, 0x18, 0xbd, 0xc7, 0x16, 0x81, 0xbe, 0xf8, 0x4a,
0x65, 0xf2, 0x5d, 0xab, 0x2b, 0x33, 0xd4, 0xa5, 0x67, 0x98,
0x9f, 0x7e, 0x2b, 0x5d, 0xc2, 0xaf, 0x8e, 0x3a, 0x4c, 0xa5,
0x75, 0x25, 0xb4, 0x8d, 0xe3, 0x7b, 0xa3, 0x64, 0x39
};
unsigned char boom2[] =
{
0xde, 0xaa, 0x42, 0xfc, 0x9, 0xe8, 0xb2, 0x6, 0xd, 0x93,
0x61, 0xf4, 0x24, 0x49, 0x15, 0x1, 0xd7, 0xab, 0x4, 0x18,
0xcf, 0xe9, 0xd5, 0x96, 0x33, 0xca, 0xf9, 0x2a, 0x5e, 0xea,
0x2d, 0x3c, 0x94, 0x6f, 0x38, 0x9d, 0x58, 0xea
};
unsigned char ptr[] =
{
0x12, 0x0E, 0x1B, 0x1E, 0x11, 0x05, 0x07, 0x01, 0x10, 0x22,
0x06, 0x17, 0x16, 0x08, 0x19, 0x13, 0x04, 0x0F, 0x02, 0x0D,
0x25, 0x0C, 0x03, 0x15, 0x1C, 0x14, 0x0B, 0x1A, 0x18, 0x09,
0x1D, 0x23, 0x1F, 0x20, 0x24, 0x0A, 0x00, 0x21,0x00
};
for(int i=0;i<39;i++)
{
v31[i]=ciber[i]^str[i];
}
unsigned char transv31[39]={};
memset(transv31,0,sizeof(transv31));
for(int i=0;i<39;i++)
{
v31[i]^=boom2[i];

}
for(int j=0;j<39;j++)
{

transv31[ptr[j]]=v31[j];
}
memcpy(v31,transv31,39);
for(int i=0;i<38;i++)
{
v31[i]^=boom1[i];
}
v31[0]='f';
printf("%s",v31);
return 0;
}

得到flag

flag{78bace5989660ee38f1fd980a4b4fbcd}


Ciscn Reverse
http://example.com/2024/06/05/Ciscn-Reverse/
作者
peace dawn
发布于
2024年6月5日
许可协议