软件涉及违规内容,故不放出截图及相关信息
1. 首先抓包分析api通信内容
POST /api/v3/topic/index
Headers{ "User-Agent": "okhttp/4.9.0", "key": "AbA65fokJP95tnql765yv+Oqe+TKH+raRmuap1yB8ZCs6G0S+vmJLowWvFkp5Bme3W8RvT2KL81WvpC/qtQXS0PSTwcx4tWsA0V0cnRQzxmUBCZy4zWB2E/cDL9hmXp/nJUEAPOBkjQst1ePBrOnyUWPMOeJplDExRz3ylaRvEM\u003d", "value": "A0190EA678EB6BCDA6003FFAAACB48EF1428BAAC52281205457E0BBBBE46F07276F444542DC01ACFF9432E57195C5DEAB03EE2B5142304D579D2913EF81B12E086E6F82C63B3C8623A98AA0C800C2A39AC05B182EDF4FBBEC18F86129094508E9B7D8825F442E02A123768588A427449853BF4BA760301D8B7C8ED86240A778D577AD0C3D766673F8FDB989944C661D4F22B7C670F0BF5E513CFA03947275F53E8D2EDDC1CC4667A5195BB94FB63B2F1", "Content-Type": "application/x-www-form-urlencoded", "……": "……" }
Text
params=9B58D5DC0EE5334D2D18B3C12F273C1B1CC564442181AEDBA1B7840001863B923CDB02D42387198503F40C1AD1AAC3E806DB77A6F2D61FB0C1CAB1CD9384A19A10815E8B13EEA90593B8A91C8766AF78D0FCF3402F8F2F38F02271B8F15B2DAC190630470478610DDDE569533E0054F282143A3DE1C83AD9FE53C33335BA6D30
Response
Headers{ "Server": "nginx", "Content-Type": "application/json; charset\u003dutf-8", "key": "B6QzS4Zb0R7Z8fjr2JotRAc1YZFNeG3TVHZlHqIeLMnssXpO44DX+vQMfLEQnbMa5VMZ5ll69hI26M0/cqc4zLrIIa5b9z9GtD+IZZVbqvO59vQx4CNhFbTJf5HRhbl/5w+taQrymEEfMigMQHP1DylB49reI81orEzTbiZOBbs\u003d", "Transfer-Encoding": "chunked", "……": "……" }
Text
"12545BA2F8F7AC28E7C02B7D7D8C215BECE81FACAD805064948355C579088652DFFB2885AE1608639AFBFB02024E31EA2CF5511572918DACC260E503B882E011512D7C6FD0CF53BB5C79C6095AE4CCBBAEA59CA043FD081C0F6AFCF7F5C376C91B978918977F5A51F492A46F0A6E1D97F1A90106E28C31CB20D27FA3CDE9A2D46652DADEA46F74……"
发现请求和响应全部为加密数据,在请求的Headers
中有关键词key
和value
,响应的Headers
中同样包含关键词key
,请求和响应的内容都是十六进制密文。
首次接触这种加密,最开始有点无从下手的感觉。猜测key
、value
的加密方式,容易看出key
是base64编码后的密文,value
和Text
的这种hex格式则有多种可能,hash、DES、AES、RSA等……由于hash的不可逆,hex应该为DES等加密后的密文。
首先尝试直接base64解码key
的内容,没有成功。
因此说明key
不是明文直接base64编码,而是把明文加密后的cipher进行编码,与value
和Text
的hex相似。
这时候只看这个Packet是分析不出任何内容的,全部信息都是加密的并且没有密码。所以在抓包内容中继续查找有用信。当翻到软件启动时的前几个请求时,发现了一个API非常可疑。如下:
api/v3/support/keys
查看Response内容,不是密文!包含一个公钥。
{
"code":200,
"data":{"public_key":"-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvvn357aKesK5kf\/sASluITOcb\nBNU\/r\/Hyzjtg\/xEr3Cc09h2k+\/1noqG5YhSkUXwsAf7okdirwPfQNEMB1yaYaiaC\nsdkcQF8ER6bGkHiDGAq9F32Iyojj0ci4zh9LnspOmqazt9FYXujAD12BbiEVv16C\n1MgH6tDteRCbZUpLqwIDAQAB\n-----END PUBLIC KEY-----"},
"msg":"success"
}
当看到公钥时大喜过望,原本以为要debug软件得到解密信息,没想到直接通过抓包拿到了。
尝试用公钥去解密服务器的Headers中的key
,成功得到了一组数据。
key
和iv
,即为密码和偏移量。易知这两个参数用来解密其它内容,尝试用它们去解密服务器响应的Text密文,依旧成功。
至此思路已经很清晰,客户端拥有一个公钥用来解密响应中的key
,从key
中得到密码和偏移量继续解密响应内容。
由于客户端有公钥,猜测请求Headers中的key
也是用公钥进行加密,加密内容为密码和偏移量,这组密码用来解密请求的Text中的PARAMS=……中的加密内容。现在Haders中还有一个value
不知道是用来做什么的,但根据格式猜测它和Text中的密文一样,可以用key
中的密码和偏移量解密。
2. 验证对请求内容的猜测
由非对等加密的一端加密一端解密的特点,客户端加密的内容无法用客户端的公钥解密,只能用服务端的私钥进行解密。显然私钥几乎不可能拿到。
这时候突然有一个想法:我自己生成一个密钥对,并用其中的公钥替换接口api/v3/support/keys
中的公钥,这时候客户端无法解密服务器的内容,但是可以用私钥去解密客户端的请求。
实现劫持注入的工具很多,很轻松地完成了密钥接口中公钥的替换。当用与注入公钥对应的私钥去解密APP请求的key
时,成功拿到了key
和iv
,与猜测相符。继续验证这组密码能否解密PARAMS,依然成功。最后尝试解密value
,还是成功拿到了明文。
猜测验证成功。
3. 通信过程还原
经过上面的猜测和分析,已经大致得出客户端和服务器的通信过程。
首先,APP启动初始化时从密钥接口中拿到用来加密和解密的公钥。
当APP和服务器通信时,先随机生成一组密码和偏移量,并用这组密码加密请求的内容。请求的内容被分为两部分,分别放在Headers中的value
和Text中,然后用之前的公钥加密这组密码,并把加密后的密码放在Headers中的key
中。
服务器接收到客户端请求时,首先从Headers中拿到key
,用自己的私钥去解密得到其中的密码。然后用得到的密码去进一步解密value
和Text中的内容。接下来响应客户端,同样随机生成一组密码,并用它们加密响应内容,加密后的密文直接放在响应的Text中,然后用私钥加密这组密码,把加密后的密码放在响应Headers中的key
中。
APP接收服务器的响应,从Headers中取出key
用公钥解密得到密码,然后用密码解密Text得到服务器的响应内容。