burp到期了,按照以往的情况,很快就会有大佬放出更新版本,但等待的时间着实难熬。
一直改系统时间有些麻烦,所以写个小东西方便群众。
(我是ms党,所以……linux和mac自求多福。)
0x01 原理
windows上的jre使用GetSystemTimeAsFileTime API获取系统时间,对API下个断点,把poi(esp+4)改成0x01d263c1`feb0c000,就能看到所有的时间都变成了2017/1/1 X:0:0:
bp kernelbase!GetSystemTimeAsFileTime "r @$t0=poi(esp+4);gu;eq @$t0 0x01d263c1`feb0c000;g"
之后burp就能打开了:
中文操作系统默认时区是东八区,所以时间是2017/1/1 8:0:0,其他系统以此类推。
但现在出现了一个问题:由于所有时间都变成了相同的,所以history等按照时间排序的功能就失效了。
解决方式也很简单,只改日期不改时间即可。GetSystemTimeAsFileTime被我们和谐了,换用GetSystemTime来获取时间,返回的SYSTEMTIME也更方便处理。
(windows时间API基本都是从SharedUserData中直接取值,所以不用担心修改一个API会影响到其他的问题)
0x02 代码
burp的进程是javaw,所以必须要做个hook。
注入+hook的代码网上一找一大把,不过java提供了agent功能进行动态修改,其中native agent本身就是一个dll,这样就不用单独写一个注入的exe了。
native agent需要导出三个函数:Agent_OnLoad和Agent_OnAttach用于初始化,Agent_OnUnload用于卸载,考虑到并不需要访问jvm信息,用PVOID和long代替jvm类型:
long WINAPI Agent_OnLoad(PVOID *vm, char *options, void *reserved); long WINAPI Agent_OnAttach(PVOID *vm, char *options, void *reserved); long WINAPI Agent_OnUnload(PVOID *vm);
hook实现方面,需要用到两个API:GetSystemTime获取当前时间,把年月日改成2017/1/1;
SystemTimeToFileTime将修改后的时间转换为FileTime并返回传递给原始调用:
void WINAPI hook(LPFILETIME ft) { SYSTEMTIME st = { 0 }; GetSystemTime(&st); st.wYear = 2017; st.wMonth = 1; st.wDay = 1; SystemTimeToFileTime(&st, ft); }
之后是hook,直接jmp,考虑到64位jre的问题要写两种:
#ifdef WIN64 BYTE shellcode[] = { 0x48, 0xb8, //mov rax, 0, 0, 0, 0, 0, 0, 0, 0, //hook addr 0xff, 0xe0 //jmp rax }; #else BYTE shellcode[] = { 0x90, 0xb8, //mov eax, 0, 0, 0, 0, //hook addr 0xff, 0xe0 //jmp rax }; #endif
编译加载运行,发现burp直接退出了,反编译BurpLoader,看到了一个可疑调用:
(吐槽一句jd-gui,反编译出的字节码结果还不如javap)
查询官方文档 https://docs.oracle.com/javase/7/docs/api/java/lang/management/RuntimeMXBean.html 得知getInputArguments方法返回jvm参数配置信息,反编译jre发现最终调用了一个native实现:
sun.management.VMManagementImpl.getVmArguments0。
native实现必然封装于dll中,退出之前加载的最后一个java模块为management.dll:
查看导出函数,果然发现了名为_Java_sun_management_VMManagementImpl_getVmArguments0@8的导出。
那么和谐这个函数就好了。
由于java层的包装会自动处理null的问题,也就不用费力气写hook函数了,改成return NULL即可:
#ifdef WIN64 BYTE shellcode2[] = { 0x48, 0x33, 0xc0, //xor rax,rax 0xc3, 0x00, 0x00 //ret }; #else BYTE shellcode2[] = { 0x33, 0xc0, //xor eax,eax 0xc2, 0x08, 0x00 //ret 8 }; #endif
编译加载运行,这次没有问题了:
0x03 下载
编译好的dll为JavaTimeAgent和JavaTimeAgent64,使用方法类似于指定xmx,给java加个启动参数即可:
java -agentpath:JavaTimeAgent.dll java_class javaw -agentpath:JavaTimeAgent.dll -jar BurpLoader.jar
运行后的日期被锁定在2017/1/1,时间不变。如果有特殊需求的话自行修改编译dll。
注意几个细节:
java的环境变量要去控制面板配置;jar和dll最好写绝对路径。
hook的行为可能被杀软和谐。
dll的版本要和jre匹配。
其他检测时间的java程序应该也许可能好像大概差不多能使用这个工具,请自行尝试。
我测试的环境为win7 x86/win10 x64+jre 1.8,其他版本没有环境来测试(理论上不会有问题……吧)。
下载地址: JavaTimeAgent.zip
Github: https://github.com/zcgonvh/JavaTimeAgent
解压密码见注释。