Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Latest commit

 

History

History
History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

README.md

Outline

Windows 通用回显

说明

看了 lufei 师傅的文章 《win描述符下成功又失败的回显》,才知道原来在 Windows NIO/BIO 中也有类似 LinuxFileDescriptor 的存在,虽然通过查看 JNI 的源码知道是一个句柄文件,但是用 Java 代码处理起来都是类似的。

Windows NIO/BIO 是通过 JNI 调用 winsock2.hSOCKET WSAAPI accept(SOCKET s,sockaddr *addr,int *addrlen); 函数获取 socket, 随后将其转换成 jint 返回给 Java 程序,存储为 FileDescriptor。在向 socket 返回数据时, Java 代码再把 FileDescriptor 通过 JNI 转换为 SOCKET 传递给 int WSAAPI WSASend(SOCKET s,LPWSABUF lpBuffers,DWORD dwBufferCount,LPDWORD lpNumberOfBytesSent,DWORD dwFlags,LPWSAOVERLAPPED lpOverlapped,LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine); 函数,从而完成数据的发送。

开始的时候,想着可以通过遍历 fd 的值,利用反射创建对应的 FileDescriptor,然后通过 JNI 转换成 SOCKET 并传递给 getpeername 函数尝试去获取对端地址,如果能拿到结果,说明 fd 的值是有效的, 对应着一个有效的 socket。 然而实践之后并没有拿到想要的结果。由于对 c 近乎一窍不通,于是只能放弃这种方式,转而从 Java 代码中尝试去寻找是否有接受 FileDescriptor 作为参数并返回一些信息的静态方法。结果果然找到了 sun.nio.ch.Net#remoteAddress , 这个方法返回的结果就是我最开始时想通过 JNI 方式拿到的结果。

于是,一切就很简单了,遍历 fd 的值,利用反射创建对应的 FileDescriptor,然后调用 sun.nio.ch.Net#remoteAddress 确认 FileDescriptor 的有效性,如果有效,往里面写数据, 从而实现回显。

效果

Tomcat 9.0.33Jetty 9.4.30.v20200611Resin/4.0.64 中测试通过 Tomcat Jetty Resin

参考

Morty Proxy This is a proxified and sanitized view of the page, visit original site.