Re1:
程序是用rust写的,还把符号表删了,先用bindiff恢复符号表,观察main函数:
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 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
| int __fastcall main_0(int argc, const char **argv, const char **envp) {
v52 = -2i64; v43 = 0i64; v42 = 0i64; v41 = 0i64; *(_OWORD *)input = 0i64; v44 = alloc::vec::Vec$LT$T$C$A$GT$::reserve::h59c5a926bf455501(*(_QWORD *)&argc, argv, envp); if ( (std::sys_common::backtrace::print((volatile signed __int8 **)&v44, (char *)input, 0x40ui64) & 1) != 0 ) { _ok_n_ = (char **)n0x41; core::result::unwrap_failed::h1ffdf61359d262b8( (unsigned int)"called `Result::unwrap()` on an `Err` valuesrc/main.rs", 43, (unsigned int)&_ok_n_, (unsigned int)&off_7FF66FA3C3A0, (__int64)&off_7FF66FA3C428); } if ( n0x41 >= 0x41 ) sub_7FF66FA3B520(n0x41, 64i64, &off_7FF66FA3C440); sub_7FF66FA347D0(&_ok_n_, input, n0x41); n0x41_2 = (__int64)_ok_n_; Src_1 = (char *)Src; Src_4 = (char *)Src + len; if ( len ) { length = 0i64; v8 = 0i64; Src_2 = (char *)Src; do { Src_3 = Src_2; v12 = v8; n0xF0 = *Src_2; n0x80 = (unsigned __int8)n0xF0; if ( n0xF0 < 0 ) { v15 = n0xF0 & 0x1F; v16 = Src_3[1] & 0x3F; if ( (unsigned __int8)n0xF0 <= 0xDFu ) { Src_2 = Src_3 + 2; n0x80 = v16 | (v15 << 6); } else { v17 = (v16 << 6) | Src_3[2] & 0x3F; if ( (unsigned __int8)n0xF0 < 0xF0u ) { Src_2 = Src_3 + 3; n0x80 = (v15 << 12) | v17; } else { Src_2 = Src_3 + 4; n0x80 = ((v15 & 7) << 18) | (v17 << 6) | Src_3[3] & 0x3F; } } } else { Src_2 = Src_3 + 1; } v8 = &v12[Src_2 - Src_3]; if ( n0x80 - 9 >= 5 && n0x80 != 32 ) { if ( n0x80 < 0x80 ) goto LABEL_28; n48 = n0x80 >> 8; if ( n0x80 >> 8 > 0x1F ) { if ( n48 == 32 ) { v10 = *((_BYTE *)off_7FF66FA46078 + (unsigned __int8)n0x80) >> 1; } else { if ( n48 != 48 ) goto LABEL_28; v10 = n0x80 == 12288; } } else if ( n48 ) { if ( n48 != 22 ) goto LABEL_28; v10 = n0x80 == 5760; } else { v10 = *((_BYTE *)off_7FF66FA46078 + (unsigned __int8)n0x80); } if ( (v10 & 1) == 0 ) goto LABEL_28; } } while ( Src_2 != Src_4 ); input_2 = (char *)1; LOBYTE(v12) = 1; v51 = (int)v12; LABEL_60: Src_5 = (char *)Src; goto LABEL_61; } v12 = 0i64; v8 = 0i64; Src_2 = (char *)Src; LABEL_28: if ( Src_2 == Src_4 ) { LABEL_53: if ( len ) { length = v8 - v12; if ( v8 - v12 < 0 ) goto LABEL_74; goto LABEL_55; } input_2 = (char *)1; LOBYTE(v12) = 1; v51 = (int)v12; length = 0i64; goto LABEL_60; } while ( 1 ) { Src_6 = Src_4; n32 = *(Src_4 - 1); if ( (n32 & 0x80000000) != 0 ) break; --Src_4; if ( n32 - 9 >= 5 ) goto LABEL_43; LABEL_32: if ( Src_2 == Src_4 ) goto LABEL_53; } v23 = *(Src_4 - 2); if ( v23 >= -64 ) { Src_4 -= 2; v26 = v23 & 0x1F; } else { v24 = *(Src_4 - 3); if ( v24 >= -64 ) { Src_4 -= 3; v25 = v24 & 0xF; } else { Src_4 -= 4; v25 = ((*(Src_6 - 4) & 7) << 6) | v24 & 0x3F; } v26 = (v25 << 6) | v23 & 0x3F; } n32 = (v26 << 6) | n32 & 0x3F; if ( n32 - 9 < 5 ) goto LABEL_32; LABEL_43: if ( n32 == 32 ) goto LABEL_32; if ( n32 < 0x80 ) goto LABEL_73; n22 = n32 >> 8; if ( n32 >> 8 <= 0x1F ) { if ( n22 ) { if ( n22 != 22 ) goto LABEL_73; v20 = n32 == 5760; } else { v20 = *((_BYTE *)off_7FF66FA46078 + (unsigned __int8)n32); } goto LABEL_31; } if ( n22 == 32 ) { v20 = *((_BYTE *)off_7FF66FA46078 + (unsigned __int8)n32) >> 1; goto LABEL_31; } if ( n22 == 48 ) { v20 = n32 == 12288; LABEL_31: if ( (v20 & 1) == 0 ) goto LABEL_73; goto LABEL_32; } LABEL_73: v8 = &Src_6[v8 - Src_2]; length = v8 - v12; if ( v8 - v12 < 0 ) { LABEL_74: v30 = 0i64; LABEL_75: Src_7 = Src_1; Size_1 = n0x41_2; alloc::raw_vec::handle_error::h6dc72529d1078ae9(v30, length); } LABEL_55: Src_5 = &v12[(_QWORD)Src]; if ( v8 == v12 ) { input_2 = (char *)1; LOBYTE(v12) = 1; v51 = (int)v12; } else { Src_8 = &v12[(_QWORD)Src]; v30 = 1i64; Src_10 = (char *)_rust_alloc(length, 1i64); if ( !Src_10 ) goto LABEL_75; input_2 = Src_10; v51 = 0; Src_5 = Src_8; } LABEL_61: memcpy_0(input_2, Src_5, length); if ( 2 * n0x41_2 ) _rust_dealloc(Src_1, n0x41_2, 1i64); Size_1 = length; Src_7 = input_2; if ( length == 1 ) sub_7FF66FA3B200(1i64, 1i64, &off_7FF66FA3C410); if ( !length ) sub_7FF66FA3B200(0i64, 0i64, &off_7FF66FA3C3F8); input_1 = *(_WORD *)input_2; Buf1_1 = _rust_alloc_zeroed(length, 1i64); if ( !Buf1_1 ) alloc::raw_vec::handle_error::h6dc72529d1078ae9(1i64, length); output = (_BYTE *)Buf1_1; for ( i = 0i64; i != length; ++i ) { HIWORD(v36) = (input_1 >> 2) ^ (input_1 >> 3) ^ (input_1 >> 1); LOWORD(v36) = input_1; input_1 = v36 >> 1; v37 = __ROL1__(v36, 4); v38 = (4 * (v37 & 0x33)) | (v37 >> 2) & 0x33; output[i] = input_2[i] ^ (i + ((2 * (v38 & 0x55)) | (v38 >> 1) & 0x55)); } if ( length == 42 && !memcmp_0(output, Buf2_, 0x2Aui64) ) { _rust_dealloc(output, 42i64, 1i64); _ok_n_ = &off_7FF66FA3C4A0; Src = (void *)1; len = 8i64; v48 = 0i64; sub_7FF66FA25750(&_ok_n_); } else { _rust_dealloc(output, length, 1i64); _ok_n_ = &off_7FF66FA3C488; Src = (void *)1; len = 8i64; v48 = 0i64; sub_7FF66FA25750(&_ok_n_); } return _rust_dealloc(Src_7, Size_1, 1i64); }
|
发现有一个很简单的基于明文前2字节的流加密,密钥流仅和明文的前2字节有关,编写脚本解密:
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
| def encrypt(m): d = m[0] + (m[1] << 8) length = len(m) output = bytearray(length) for i in range(length): h = ((d >> 2) ^ (d >> 3) ^ (d >> 1)) & 0xFFFF l = d & 0xFFFF hl = (h << 16) | l d = (hl >> 1) & 0xFFFF dyn = (((hl & 0xFF) << 4) | ((hl & 0xFF) >> 4)) & 0xFF tmp = (((dyn & 0x33) << 2) | ((dyn >> 2) & 0x33)) & 0xFF res = i + (((tmp & 0x55) << 1) | ((tmp >> 1) & 0x55)) output[i] = m[i] ^ (res & 0xFF) return bytes(output)
def gen_arr(m): d = m[0] + (m[1] << 8) length = len(m) output = [None] * length for i in range(length): h = ((d >> 2) ^ (d >> 3) ^ (d >> 1)) & 0xFFFF l = d & 0xFFFF hl = (h << 16) | l d = (hl >> 1) & 0xFFFF dyn = (((hl & 0xFF) << 4) | ((hl & 0xFF) >> 4)) & 0xFF tmp = (((dyn & 0x33) << 2) | ((dyn >> 2) & 0x33)) & 0xFF res = (i + (((tmp & 0x55) << 1) | ((tmp >> 1) & 0x55))) & 0xFF output[i] = res return output
m = b"fl" + b"0" * 40 encrypted_data = encrypt(m) print("加密结果:", encrypted_data)
xor_arr = gen_arr(m) for i in range(len(xor_arr)): print(hex(xor_arr[i]),end = ", ") print() cipher = bytearray.fromhex("00A1FB531CFAF01B0640D48C16F4902742B98B0F02D731B72612067EAEDFDA68AF35CCB7B0D09A592B0B") for i in range(len(cipher)): cipher[i] ^= xor_arr[i] print(cipher.decode())
|
得到flag:flag{1c98572d-7f7b-4fbf-8750-4a2986c695ce}.
Re2:
查看main:
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
| int __fastcall main(int argc, const char **argv, const char **envp) { Stream *Stream; size_t n0x40; __int64 n32; unsigned __int64 n0x20; __m128i v8; __m128i v9; char Buffer[16]; __int128 v11; __int128 v12; __int128 v13;
sub_140001010("Enter flag: "); Stream = _acrt_iob_func(0); fgets(Buffer, 64, Stream); n0x40 = strcspn(Buffer, "\n"); if ( n0x40 >= 0x40 ) _report_rangecheckfailure(); Buffer[n0x40] = 0; n32 = -1i64; do ++n32; while ( Buffer[n32] ); if ( n32 == 32 ) { n0x20 = 0i64; v8 = _mm_loadu_si128((const __m128i *)&xmmword_1400032F8); xmmword_140005630 = v11; xmmword_140005620 = *(_OWORD *)Buffer; xmmword_140005650 = v13; v9 = _mm_loadu_si128((const __m128i *)&xmmword_1400032E8); xmmword_140005640 = v12; do { *(__m128i *)&Buffer[n0x20] = _mm_add_epi8(_mm_shuffle_epi8(_mm_loadu_si128((const __m128i *)&Buffer[n0x20]), v8),v9); n0x20 += 16i64; } while ( n0x20 < 0x20 ); if ( !memcmp(Buffer, "cge87k?9<>?@=pss393=>;8@:Cp@DAuH", 0x20ui64) ) sub_140001010("Correct! The flag is flag{%s}\n"); else puts("Wrong!"); return 0; } else { puts("Wrong!"); return 1; } }
|
编写脚本解密:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import numpy as np
v8 = np.array([[0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00],], dtype=np.uint8) v9 = np.array([[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10],], dtype=np.uint8)
target = "cge87k?9<>?@=pss393=>;8@:Cp@DAuH" target_bytes = np.frombuffer(target.encode(), dtype=np.uint8) decrypted = [] for i in range(0, len(target_bytes), 16): block = target_bytes[i:i+16] sub_block = (block - v9[0]) & 0xFF inv_shuffle = np.argsort(v8[0]) decrypted_block = sub_block[inv_shuffle] decrypted.extend(decrypted_block) flag = bytes(decrypted).decode() print(f"flag{{{flag}}}")
|
得到flag:flag{cdb0444318e24beb8f374e9181599072}.
re!!!!!
ios逆向,查询字符串得到一串密文:c2a7c3b9c2acc3a5c2a2c3b6c391c295c2aac38cc28bc38ac2a6c3aec28bc28fc2a1c3aac287c382c2bfc3b6c282c38ec2b9c3a2c2a13cc28ac3adc2b1c280c2b2c384c28dc3bbc283c396c2b03dc28a3bc2b12cc287c3b0c2852bc282c39ac28432c29320c29d21c29ac392c291c3a1c296c3a06d1866396c256310c299c3946931c291c3917a2e470b632a7811730f65c385,发现密文貌似有某种规律(绝大部分都是c2xx、c3xx).
找到初始化函数:
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
| id __fastcall ViewController.init(coder:)(void *obj) { char *receiver; char *v3; char *v4; void *obj_1; objc_super v7;
v3 = &receiver[OBJC_IVAR____TtC9challenge14ViewController_secretKey]; *(_QWORD *)v3 = 0x616B696875726148LL; *((_QWORD *)v3 + 1) = 0xEA00000000006567LL; v4 = &receiver[OBJC_IVAR____TtC9challenge14ViewController_flagHash]; *(_QWORD *)v4 = 0xD000000000000126LL; *((_QWORD *)v4 + 1) = 0x8000000100003C20LL; *(_QWORD *)&receiver[OBJC_IVAR____TtC9challenge14ViewController_magicNumber] = 0xDEADBEEFLL; *(_QWORD *)&receiver[OBJC_IVAR____TtC9challenge14ViewController_inputTextField] = 0; *(_QWORD *)&receiver[OBJC_IVAR____TtC9challenge14ViewController_outputTextField] = 0; *(_QWORD *)&receiver[OBJC_IVAR____TtC9challenge14ViewController_encryptButton] = 0; v7.receiver = receiver; v7.super_class = (Class)type metadata accessor for ViewController(obj); obj_1 = objc_retainAutoreleasedReturnValue(objc_msgSendSuper2(&v7, "initWithCoder:", obj)); objc_release(obj); if ( obj_1 ) objc_release(obj_1); return obj_1; }
|
发现这里有一个secretKey
被初始化,转换端序得到密钥Haruhikage.
在void ViewController.encryptButtonClicked()()
中有:
1 2 3 4 5 6 7 8 9 10 11 12
| v10 = ViewController.complexEncrypt(_:)(p___swiftEmptyArrayStorage, v9); v12 = v11; v13 = ViewController.verifyFlag(_:)(p___swiftEmptyArrayStorage, v9); swift_bridgeObjectRelease(); if ( (v13 & 1) != 0 ) { swift_bridgeObjectRelease(); obj_1 = *(void **)(v2 + OBJC_IVAR____TtC9challenge14ViewController_outputTextField); if ( obj_1 ) goto LABEL_7; goto LABEL_12; }
|
查看关键函数__int64 __fastcall ViewController.complexEncrypt(_:)(unsigned __int64 p___swiftEmptyArrayStorage, unsigned __int64 a2)
:
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
| __int64 __fastcall ViewController.complexEncrypt(_:)(unsigned __int64 p___swiftEmptyArrayStorage, unsigned __int64 a2) { __int64 v2; __int64 v5; __int64 v6; char *v7; unsigned __int64 v8; __int64 v9; __int64 v10; __int64 v11; unsigned __int64 v12; unsigned __int64 v13; __int64 _countAndFlagsBits; void *_object; Swift::String v16; void *v17; unsigned __int64 v18; unsigned __int64 v19; __int64 v20; __int64 v22;
v5 = type metadata accessor for String.Encoding(); v6 = *(_QWORD *)(v5 - 8); v7 = (char *)&v22 - ((*(_QWORD *)(v6 + 64) + 15LL) & 0xFFFFFFFFFFFFFFF0LL); v8 = specialized ViewController.rc4Encrypt(_:key:)( p___swiftEmptyArrayStorage, a2, *(_QWORD *)(v2 + OBJC_IVAR____TtC9challenge14ViewController_secretKey), *(_QWORD *)(v2 + OBJC_IVAR____TtC9challenge14ViewController_secretKey + 8)); v10 = v9; static String.Encoding.utf8.getter(); v11 = String.data(using:allowLossyConversion:)(v7, 0, v8, v10); v13 = v12; swift_bridgeObjectRelease(); (*(void (__fastcall **)(char *, __int64))(v6 + 8))(v7, v5); if ( v13 >> 60 == 15 ) { _countAndFlagsBits = 0; _object = (void *)0xE000000000000000LL; } else { v16 = Data.base64EncodedString(options:)(0); _object = v16._object; outlined consume of Data?(v11, v13); _countAndFlagsBits = v16._countAndFlagsBits; } v17 = specialized ViewController.obfuscateString(_:)(_countAndFlagsBits, (unsigned __int64)_object); v19 = v18; swift_bridgeObjectRelease(); v20 = specialized ViewController.transformString(_:)((__int64)v17, v19); swift_bridgeObjectRelease(); return v20; }
|
可以发现其加密逻辑为RC4(密钥为上文被初始化的密钥)→base64编码→obfuscateString→transformString,先查看最后一个加密:
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 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
| void *__fastcall specialized ViewController.transformString(_:)(__int64 a1, unsigned __int64 a2) { unsigned __int64 v2; void *_countAndFlagsBits; Swift::String_optional v4; void *_object; __int64 i; __int64 v7; unsigned int tmp; unsigned int res; Swift::String v10; Swift::String_optional v11; int v12; int dual; int v14; int tri_1; int tri; _QWORD v17[5]; void *_object_1; unsigned __int64 v19;
_object_1 = 0; v19 = 0xE000000000000000LL; v2 = HIBYTE(a2) & 0xF; if ( (a2 & 0x2000000000000000LL) == 0 ) v2 = a1 & 0xFFFFFFFFFFFFLL; v17[1] = a1; v17[2] = a2; v17[3] = 0; v17[4] = v2; swift_bridgeObjectRetain(a2); v4 = String.Iterator.next()(); _countAndFlagsBits = (void *)v4.value._countAndFlagsBits; _object = v4.value._object; if ( v4.value._object ) { i = 0; while ( !__OFADD__(i, 1) ) { v7 = specialized Collection.first.getter(_countAndFlagsBits, _object); _countAndFlagsBits = (void *)swift_bridgeObjectRelease(); if ( (i & 1) != 0 ) { tmp = v7 ^ 0xBE; if ( (v7 & (unsigned __int64)&_mh_execute_header) != 0 ) tmp = 0xBE; if ( tmp >> 11 == 27 ) goto LABEL_30; if ( tmp > 0x10FFFF ) goto LABEL_27; } else { tmp = v7 ^ 0xEF; if ( (v7 & (unsigned __int64)&_mh_execute_header) != 0 ) tmp = 0xEF; if ( tmp >> 11 == 27 ) goto LABEL_29; if ( tmp > 0x10FFFF ) goto LABEL_28; } if ( tmp > 0x7F ) { v12 = (tmp & 0x3F) << 8; dual = (tmp >> 6) + v12 + 0x81C1; v14 = (v12 | (tmp >> 6) & 0x3F) << 8; tri_1 = (tmp >> 18) + ((v14 | (tmp >> 12) & 0x3F) << 8) - 0x7E7E7E0F; tri = (tmp >> 12) + v14 + 0x8181E1; if ( HIWORD(tmp) ) tri = tri_1; if ( tmp >= 0x800 ) res = tri; else res = dual; } else { res = tmp + 1; } v17[0] = (res + 0xFEFEFEFEFEFEFFLL) & ~(-1LL << (8 * (4 - (unsigned __int8)(__clz(res) >> 3)))); v10._countAndFlagsBits = static String._uncheckedFromUTF8(_:)(v17); String.append(_:)(v10); swift_bridgeObjectRelease(); v11 = String.Iterator.next()(); _countAndFlagsBits = (void *)v11.value._countAndFlagsBits; _object = v11.value._object; ++i; if ( !v11.value._object ) { _object = _object_1; goto LABEL_25; } } __break(1u); LABEL_27: __break(1u); LABEL_28: __break(1u); LABEL_29: __break(1u); LABEL_30: __break(1u); } else { LABEL_25: swift_bridgeObjectRelease(); return _object; } return _countAndFlagsBits; }
|
发现是按奇偶索引分别异或0xBE和0xEF,最后还有一个utf-8的转换函数,同构这个函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| def calc_utf8(tmp: int) -> int: if tmp > 0x7F: v12 = (tmp & 0x3F) << 8 v13 = ((tmp >> 6) & 0x3F) + v12 + 0x81C0 v14 = ((v12 | ((tmp >> 6) & 0x3F)) << 8) v15 = ((tmp >> 18) & 0x3F) + (((v14 | ((tmp >> 12) & 0x3F)) << 8)) - 0x7E7E7E0F v16 = ((tmp >> 12) & 0x3F) + v14 + 0x8181E0 if tmp > 0xFFFF: v16 = v15 if tmp >= 0x800: v9 = v16 else: v9 = v13 else: v9 = tmp return v9
for i in range(0x0,0x100): ui = calc_utf8(i) if i >= 0x80: ui = ((ui << 8) + (ui >> 8)) & 0xFFFF print(f"{ui:04x}",end="") else: print(f"{ui:02x}",end="")
|
发现在转换结果上存在以下对应关系:
1 2 3
| 0x00 ~ 0x7F → 不变 0x80 ~ 0xBF → 加了一个C2的尾缀并转换端序 0xC0 ~ 0xFF → 减去0x40,加了一个C3的尾缀并转换端序
|
这样就知道密文中的C2和C3是哪来的了,是经过这个转换函数得到的,而这个转换函数实际上只是将每个字符切分为了三种情况,对应的实际上是utf-8的单/双/三字节编码,接下来看obfuscateString
:
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 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| void *__fastcall specialized ViewController.obfuscateString(_:)(__int64 _countAndFlagsBits, unsigned __int64 _object) { unsigned __int64 v2; void *_countAndFlagsBits_1; Swift::String_optional v4; void *_object_1; __int64 i; __int64 v7; __int64 v8; bool v9; __int64 v10; __int64 v11; bool v12; unsigned int v13; Swift::String v14; Swift::String_optional v15; _QWORD v16[5]; void *_object_2; unsigned __int64 v18;
_object_2 = 0; v18 = 0xE000000000000000LL; v2 = HIBYTE(_object) & 0xF; if ( (_object & 0x2000000000000000LL) == 0 ) v2 = _countAndFlagsBits & 0xFFFFFFFFFFFFLL; v16[1] = _countAndFlagsBits; v16[2] = _object; v16[3] = 0; v16[4] = v2; swift_bridgeObjectRetain(_object); v4 = String.Iterator.next()(); _countAndFlagsBits_1 = (void *)v4.value._countAndFlagsBits; _object_1 = v4.value._object; if ( v4.value._object ) { i = 0; while ( !__OFADD__(i, 1) ) { v7 = specialized Collection.first.getter(_countAndFlagsBits_1, _object_1); _countAndFlagsBits_1 = (void *)swift_bridgeObjectRelease(); v8 = (unsigned int)v7; if ( (v7 & (unsigned __int64)&_mh_execute_header) != 0 ) v8 = 0; v9 = __OFADD__(v8, i); v10 = v8 + i; if ( v9 ) goto LABEL_20; v9 = __OFADD__(v10, 0xDEADBEEFLL); v11 = v10 + 0xDEADBEEFLL; if ( v9 ) goto LABEL_21; v12 = -v11 < 0; v11 = (unsigned __int8)v11; if ( !v12 ) v11 = -(__int64)(unsigned __int8)-(char)v11; if ( v11 < 0 ) goto LABEL_22; if ( (v11 & 0xFFFFFF80) != 0 ) v13 = (((v11 & 0x3F) << 8) | ((unsigned int)v11 >> 6)) + 0x81C1; else v13 = v11 + 1; v16[0] = (v13 + 0xFEFEFEFEFEFEFFLL) & ~(-1LL << (8 * (4 - (unsigned __int8)(__clz(v13) >> 3)))); v14._countAndFlagsBits = static String._uncheckedFromUTF8(_:)(v16); String.append(_:)(v14); swift_bridgeObjectRelease(); v15 = String.Iterator.next()(); _countAndFlagsBits_1 = (void *)v15.value._countAndFlagsBits; _object_1 = v15.value._object; ++i; if ( !v15.value._object ) { _object_1 = _object_2; goto LABEL_18; } } __break(1u); LABEL_20: __break(1u); LABEL_21: __break(1u); LABEL_22: __break(1u); } else { LABEL_18: swift_bridgeObjectRelease(); return _object_1; } return _countAndFlagsBits_1; }
|
发现也有一个转换的结构,加密方式是加上索引i和固定值0xDEADBEEF后&0xFF,逆向这两步加密:
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
| hex_enc = "c2a7c3b9c2acc3a5c2a2c3b6c391c295c2aac38cc28bc38ac2a6c3aec28bc28fc2a1c3aac287c382c2bfc3b6c282c38ec2b9c3a2c2a13cc28ac3adc2b1c280c2b2c384c28dc3bbc283c396c2b03dc28a3bc2b12cc287c3b0c2852bc282c39ac28432c29320c29d21c29ac392c291c3a1c296c3a06d1866396c256310c299c3946931c291c3917a2e470b632a7811730f65c385"
def de_utf(hex_enc): res = bytearray() for i in range(0, len(hex_enc), 2): idx = hex_enc[i:i+2] if idx == "c2": val = int("0x"+hex_enc[i+2:i+4], 16) res.append(val) elif idx == "c3": val = int("0x"+hex_enc[i+2:i+4], 16) + 0x40 res.append(val) else: sub = hex_enc[max(i-2,0):i] if not (sub == "c2" or sub == "c3"): val = int("0x"+hex_enc[i:i+2], 16) res.append(val) return res
dec3 = de_utf(hex_enc) for i in range(len(dec3)): if i % 2 == 1: dec3[i] ^= 0xBE else: dec3[i] ^= 0xEF
dec2 = de_utf(dec3.hex())
for i in range(len(dec2)): dec2[i] = (dec2[i] - i - 0xDEADBEEF) & 0xFF
print(dec2.decode())
|
得到base64:YWRiZTI5NzkzNTg3OTgzMDhjOTExZGQ0NjQ3YTJmNmExM2MwNDJjYzMyNDU5N2UxZWRiYzA4OWE5ZTkwMTVmYmE5,解码得到一串十六进制:adbe2979358798308c911dd4647a2f6a13c042cc324597e1edbc089a9e9015fba9,RC4解密得到flag:flag{N4nd3_H4ruhik4g3_Y4tt4n0?!!}.