续上篇。 1,样本下载地址,安卓,苹果链接:https://pan.baidu.com/s/1XbpkOp3t80zn1ekmJKjAOw 提取码:ys9v 2,上篇提到了两个第三方框架,附上github 地址: https://github.com/smallbuer/flutter_aes_ecb_pkcs5 ,加密解密。 https://github.com/wozhizhizhi/flutter_getuuid.git ,设备指纹数据 3,直接hookios 的代码: //int64 fastcall Precompiled_FlutterAesEcbPkcs5_encryptStringasync_op_18489( int64 a1, int64 a2, int64 a3, int64 a4, int64 a5) 再IDA 里看到这个函数,好像尝试下,觉得hook ,拿到函数基地址,然后直接hook 参数,从内存读取字符串。 IDA 设置基地址: 编辑---》段--》 重新设置基地址,如图 设置为0 ,然后找到函数的地址: function get_func_addr(module, offset) {
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var base_addr
=
Module.findBaseAddress(module);
console.log(
"base_addr: "
+
base_addr);
console.log(hexdump(ptr(base_addr), {
length:
16
,
header: true,
ansi: true
}))
var func_addr
=
base_addr.add(offset);
if
(Process.arch
=
=
'arm'
)
return
func_addr.add(
1
);
/
/
如果是
32
位地址
+
1
else
return
func_addr;
}
//int64 fastcall Precompiled_FlutterAesEcbPkcs5_encryptStringasync_op_18489( int64 a1, int64 a2, int64 a3, int64 a4, int64 a5) //{
///000000000054F8D8 Precompiled_FlutterAesEcbPkcs5_encryptStringasync_op_18489 int64 a1, int64 a2, int64 a3, int64 a4, int64 a5 var func_addr = get_func_addr('App', 0x54F8D8); console.log('func_addr: ' + func_addr);
console.log(hexdump(ptr(func_addr), { length: 16, header: true, ansi: true }))
Interceptor.attach(ptr(func_addr), { onEnter: function(args) {
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
console.log(
"onEnter"
);
/
/
var num1
=
args[
0
];
/
/
console.log(num1);
/
/
send(num1)
/
/
/
print_dump(args[
0
],
100
);
print_dump(args[
1
],
100
);
print_dump(args[
2
],
100
);
print_dump(args[
3
],
100
);
print_dump(args[
4
],
100
);
/
/
console.log(Memory.readCString(num1));
/
/
Memory.readAnsiString(args[
4
])
or
Memory.readCString(args[
4
])
},
onLeave: function(retval) {
console.log(
"onLeave"
);
console.log(retval)
send(retval)
/
/
retval.replace(
3
);
/
/
返回值替换成
3
/
/
print_dump(retval,
9999
);
}
});
function print_dump(addr,size){ var buf = Memory.readByteArray(addr,size) console.log("[function] send@ " + addr.toString() + " "+ "length: " + size.toString() + "\n[data]") console.log(hexdump(buf, { offset: 0, length: size, header: false, ansi: false })); console.log("") }
/* 00000000 03 51 00 00 00 00 00 40 00 00 00 00 00 00 00 45 .Q.....@.......E 00000010 36 46 46 41 34 32 33 39 43 46 36 34 37 31 34 33 6FFA4239CF647143 00000020 38 39 35 33 42 41 45 44 31 31 30 34 45 36 44 04 8953BAED1104E6D.
*/
var func_addr = get_func_addr('App', 0x54F8D8);, App ,就是ios app运行的程序,0x54F8D8函数基地址,然后hook 上, 输出了几个参数, 有用的好像是 6FFA4239CF6471,好像对应的是请求里边的一个数据:
。自己写了一份flutter 代码,尝试了下,这个6Fxxx 不是签名的key。 继续翻代码,flutter_aes_ecb_pkcs5项目中的, /字符串加密(16进制)
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
插入代码
继续翻代码,flutter_aes_ecb_pkcs5项目中的,
/
字符串加密(
16
进制)
+
(NSString
*
)encyptPKCS5:(NSString
*
)plainText WithKey:(NSString
*
)key{
/
/
把string 转NSData
NSData
*
data
=
[plainText dataUsingEncoding:NSUTF8StringEncoding];
/
/
length
size_t plainTextBufferSize
=
[data length];
const void
*
vplainText
=
(const void
*
)[data bytes];
uint8_t
*
bufferPtr
=
NULL;
size_t bufferPtrSize
=
0
;
size_t movedBytes
=
0
;
bufferPtrSize
=
(plainTextBufferSize
+
kCCBlockSizeAES128) & ~(kCCBlockSizeAES128
-
1
);
bufferPtr
=
malloc( bufferPtrSize
*
sizeof(uint8_t));
memset((void
*
)bufferPtr,
0x0
, bufferPtrSize);
/
/
解密
hex
加密的密钥
char
*
publicKey
=
[FlutterAesEcbPkcs5Plugin convertHexStrToChar:key];
NSLog(@
"vkey->len->%d"
,strlen(publicKey));
/
/
配置CCCrypt
CCCryptorStatus ccStatus
=
CCCrypt(kCCEncrypt,
kCCAlgorithmAES128,
/
/
3DES
kCCOptionECBMode|kCCOptionPKCS7Padding,
/
/
设置模式
publicKey,
/
/
key
kCCKeySizeAES128,
nil,
/
/
偏移量,这里不用,设置为nil;不用的话,必须为nil,不可以为@“”
vplainText,
plainTextBufferSize,
(void
*
)bufferPtr,
bufferPtrSize,
&movedBytes);
if
(ccStatus
=
=
kCCSuccess) {
NSData
*
myData
=
[NSData dataWithBytes:(const char
*
)bufferPtr length:(NSUInteger)movedBytes];
/
/
16
进制(你也可以换成base64等)
NSUInteger
len
=
[myData length];
char
*
chars
=
(char
*
)[myData bytes];
NSMutableString
*
hexString
=
[[NSMutableString alloc] init];
for
(NSUInteger i
=
0
; i <
len
; i
+
+
)
[hexString appendString:[NSString stringWithFormat:@
"%0.2hhx"
, chars[i]]];
return
hexString;
}
free(bufferPtr);
return
nil;
他是调用了iOS 原生的ccrypt 加密的,所以直接hook。 执行frida-trace -U -i "CCCrypt*" RESULTNUMS, 得到frida 自动生成的代码,稍微改动一下。
//02zwncxia9i6n1lt var addr = args[3] var size = 18 var buf = Memory.readByteArray(addr,size) console.log("[function] send@ " + addr.toString() + " "+ "length: " + size.toString() + "\n[data]") console.log(hexdump(buf, { offset: 0, length: size, header: false, ansi: false })); 因为args[3] 是key,我就打印了key 的值,最终结果是:02zwncxia9i6n1lt。 Dart 代理里边示例是32位16进制的字符串,这里是18位,继续看代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
插入代码
+
(char
*
)convertHexStrToChar:(NSString
*
)hexString {
int
mallocLen
=
[hexString length]
/
2
+
1
;
char
*
myBuffer
=
(unsigned char
*
)malloc(mallocLen);
memset(myBuffer,
'\0'
,mallocLen);
for
(
int
i
=
0
; i < [hexString length]
-
1
; i
+
=
2
) {
unsigned
int
anInt;
NSString
*
hexCharStr
=
[hexString substringWithRange:NSMakeRange(i,
2
)];
NSScanner
*
scanner
=
[[NSScanner alloc] initWithString:hexCharStr];
[scanner scanHexInt:&anInt];
myBuffer[i
/
2
]
=
(char)anInt;
}
return
myBuffer;
}
还是开源项目里边的,把16进制字符串压缩成18位,我写了一个反向的c#代码,转换了一下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
插入代码
void Main()
{
testint();
string
input
=
"02zwncxia9i6n1lt"
;
string ret
=
"";
for
(
int
i
=
0
;i <
input
.Length; i
+
+
) {
char t
=
input
[i];
int
bar
=
Convert.ToInt32(t);
ret
+
=
String.
Format
(
"{0:X}"
, bar);
}
ret.Dump();
}
void testint() {
"begin"
.Dump();
}
最终输出:30327A776E637869613969366E316C74
然后按照示例,解密一下接口返回的参数:
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
插入代码
var encryptText
=
"80ff0acb4785afa19f1496b966c79c3394dfc9f7e2d333186eb49cfda094e5c02ba7217fa6697343e090679dfbbf0d9571cfdca894251bd6faff2388c0331bf20b976624c2391d3a229418bacb383f9740cbf3d5ca095525306f3d037c1260ce37a02a5d01e103229688d649a9b14a4ee84c9126c0a6b30bd586b50008a8db23006bf3bfb0d25cc834fe2c5767ad92dff37d3666e3175f21ca29b952ba6a8c12b4ce64987daeacf95052fd05943816268c1f53cdcfaa67ce6f174f8c8c2be40c0cf2e8ab71d260ce56b22f5c182c729ba8c4639f0043f8a225fd8b7ec398e937cabda159a48b774729ecc39244144b1816f6c83c0fc5aec225c1e96aa6bd696804e9f7af266d8d6892a679272e43dfb22aa1602c1a3b586b450fe42a9b1b77863f77a043dfe7c80f65080712d0ed13651ebdbc095a7f03ea9f01b9fe54f8493f5eff105f61440ac65672adc7f68ed07d753d60b58ae27f911e7a26c75fd8fd00242f12f40a2581ad37d59f7b583b4c7a192576cab7f19768dab1ffd56e05d20fb3a87636956bb4c12661023b50b2f4b377a13bc1de0fb23b14bdf7386ed58f61fd70a18d9eecd3624bb07f7e61ab87726a6e8de276d098ad62e6c8a023c8c66310bd8905dfb5e589f9f91dc973d59697b75ce2ed6be669fc27acc04529558c3c8b3afe54632e0bcf0d5dc9a0ff8dea2055d4e86f51d238c25c8238e1c3801183971665133d6113c226172e50768ceb0a28457f3794afe55f6bb71c63743b2ae14c788432d40914f66dd04dd5a8041b1d7371a722e90050e61efd329e4099926545b58a7b1aaa803b6993f10ab4823cf37d097722067125979fb282feb315fda4d0f702456dd5b49a22c8dd30ab95bef5"
;
/
/
var key
=
"8f2d0ec58552424fa74cb70823f5acfa"
;
/
/
hook 出来的
var key
=
"30327A776E637869613969366E316C74"
;
/
/
var key
=
"E6FFA4239CF6471438953BAED1104E6D"
;
var data
=
"{\"username\":\"helloword\"}"
;
/
/
generate a
16
-
byte random key
/
/
var key
=
await FlutterAesEcbPkcs5.generateDesKey(
128
);
/
/
print
(key);
/
/
encrypt
var encryptText2
=
await FlutterAesEcbPkcs5.encryptString(data, key);
/
/
time
=
2020
-
11
-
17
+
12
%
3A44
%
3A45
&version
=
2.23
&device
=
android&data
=
E6FFA4239CF6471438953BAED1104E6D&sign
=
66e29c02854094f0ad864b09cd75a025
var test2
=
"E6FFA4239CF6471438953BAED1104E6D"
;
var test3
=
"F4D2AD84F5FECE9425358C4BF968D5CC3F71217A8B027B2EFE2FB2747982BEB6"
;
print
(encryptText2);
var decryptText
=
await FlutterAesEcbPkcs5.decryptString(encryptText, key);
print
(decryptText);
返回: {"id":"11296165","username":"N6BFG1JY","nickname":"董璐蕊","phone":"","img":"http:\/\/cdn-img-new.houxiaoliang.com\/media\/headico\/20.enc?ext=.png&_v=20190812&time=1604160000&token=d8969542f2ed9aed7c72956f281844ce","group_id":"","group_name":"游客","sex":"0","group_start_time":"","group_end_time":"","share_num":"0","parent_name":"","nickname_updated":"","account_img":"http:\/\/139xb.site\/image.php?type=account&username=dcf636062de96017dd9d16954e9ace9c&ext=.png&v=1.0","can_play_tips":"3\/3","can_cache_tips":"0\/0","is_vip":"n","show_city":"1","balance":"0","level":"","level_img":"","address":""}
4,上一篇提到一个开源项目,解析libapp.so ,找不打开源项目了,付上地址。
https://pan.baidu.com/s/1XbpkOp3t80zn1ekmJKjAOw 提取码:ys9v 他的作用,看起来挺好的:
Parses 100% of the snapshot data, including memory structures.
Supports many architectures and the three snapshot types (old, AppJIT and AppAOT).
Usually zero-config: autodetects flags & settings from the snapshot.
Extracts the blobs from app.so
or .snapshot
files automatically.
Stores back-references, so you can navigate the graph easily.
Debugging output & strict mode controls.
Disassembles and analyzes the compiled code to find references to VM objects.
Examples of what you can do with the parsed info:
Extract string table of the application
Find usages of a certain object
Export metadata for Radare2
Deobfuscate a snapshot by matching it with a reference one
Generate call graph, library dependency graph, etc. 但是他只支持2019-10-23 | stable | v1.9.1+hotfix.6 版本,我想升级成新版本,但是发现比难,好看dartsdk 的源码才可以。
更多精彩内容关注我的知识星球
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2020-12-20 17:00
被ReverseApp编辑
,原因: