CS4.5改造:增加上线通知铃声
2023-10-26 13:11:54 Author: mp.weixin.qq.com(查看原文) 阅读量:4 收藏

酒零 NOVASEC

△△△点击上方“蓝字”关注我们了解更多精彩
0x00 前言
想要能够在上线的时候,语音提示[您的主机已上线!!!
仔细想想发现这个功能还有点实际用处,这样不怕错过钉钉消息.
0x01 实现思路
要实现这个功能可以分两步进行:
1、需要实现Java读取.wav.mp3文件并进行播放2、要在CS CLient找到主机上线的信号通知
另外,如果能趁这个机会找到beacon initial信号的接收点,那以后实现钉钉上线提示都不需要再启动一个无头cs客户端了
0x02 实现音频播放
先本机全局搜索.wav文件,随便找了个.wav文件作为铃声

尝试百度搜索代码,发现播放不出来,后来在github找了个Java实现录音和播放功能的代码参考才实现了完整的功能.
后面发现之所以很多wav音乐播放不出来,是因为javax.sound.sampled下的播放功能,还对wav格式有要求,如果想要播放任意wav还需要对音频格式进行检查和转换,才能保证播放时正常.
参考 https://github.com/heangping/JavaRecorder/blob/master/src/JavaRecorder.java
import common.CommonUtils;import javax.sound.sampled.*;import java.io.*;import java.util.*;
public class AudioPlayer { private static AudioPlayer audioPlayer = null; private static boolean playing = false; //记录当前播放器状态,以免重复播放 private static String defaultFormatString = null; //对不支持的wav文件都转为默认格式 private static List<String> SupportFormats = null; //记录系统支持的播放音频格式
//初始化 private AudioPlayer(){ SupportFormats = getSupportFormats(); //CommonUtils.print_info(String.format("Init Audio Player Support Formats: %s", SupportFormats.size())); defaultFormatString = getDefaultFormat(SupportFormats); CommonUtils.print_info(String.format("Init Audio Player Default Format: [%s]", defaultFormatString)); }
//单例模式,防止多次分析当前支持的环境 public static void initInstance() { if (audioPlayer == null) { audioPlayer = new AudioPlayer(); } }
//获取支持的音频编码列表 private List<String> getSupportFormats() { List<String> formatStrList = new ArrayList<>(); Mixer.Info[] mixerInfoArray = AudioSystem.getMixerInfo(); for (Mixer.Info mixerInfo : mixerInfoArray) { Mixer mixer = AudioSystem.getMixer(mixerInfo); Line.Info[] sourceLineInfoArray = mixer.getSourceLineInfo(); for (Line.Info sourceLineInfo : sourceLineInfoArray) { if (sourceLineInfo instanceof DataLine.Info) { DataLine.Info dataLineInfo = (DataLine.Info) sourceLineInfo; AudioFormat[] formats = dataLineInfo.getFormats(); for (AudioFormat format : formats) { // format.getSampleRate(), format.getSampleSizeInBits(), format.getChannels(), // format.getEncoding(), format.getFrameSize(), format.getFrameRate() //实际只需要(加密方式|chan|bits)三元组即可,其他都是可以计算出来的额 String formatStr = String.format("%s<->%s<->%s", format.getEncoding(), format.getSampleSizeInBits(), format.getChannels()); if (!formatStrList.contains(formatStr)){ formatStrList.add(formatStr); } } } } } return formatStrList; }
//获取默认转换音频格式 private String getDefaultFormat(List<String> supports){ if (supports.size()>0){ //优先使用16bit音频 1声道 String s1 = String.format("%s<->%s<->%s", "PCM_SIGNED", "16", "1"); if (supports.contains(s1)) return s1; //次优使用16bit音频 2声道 String s2 = String.format("%s<->%s<->%s", "PCM_SIGNED", "16", "2"); if (supports.contains(s2)) return s2; //否则使用第一个音频 return supports.get(0); } return null; }
//判断输入的格式是否可以播放 private static boolean isSupportedFormat(String AudioFile) { try { AudioInputStream audioInputStream = getAudioInputStream(AudioFile); AudioFormat format = audioInputStream.getFormat(); String formatStr = String.format("%s<->%s<->%s", format.getEncoding(), format.getSampleSizeInBits(), format.getChannels()); //AudioSystem.isFileTypeSupported(audioFormat.getType(), inputStream); return SupportFormats.contains(formatStr); } catch (Exception e) { //e.printStackTrace(); CommonUtils.print_error(String.format("%s Check Support Error: %s", AudioFile, e.getMessage())); return false; } }
//转换音频格式为可播放的类型 private static String convertFormat(String rawPath, String newPath, AudioFormat expectFormat) { try { //获取输入流内容 AudioInputStream audioInputStream = getAudioInputStream(rawPath); // 进行音频格式转换 AudioInputStream convertedStream = AudioSystem.getAudioInputStream(expectFormat, audioInputStream); // 写入转换后的音频文件//不会写入到jar文件内,写入到同名目录,目录不存在会报错的 // 使用mkdirs()方法创建目录(包括父目录) File newFile = new File(newPath); newFile.mkdirs(); AudioSystem.write(convertedStream, AudioFileFormat.Type.WAVE, newFile); //CommonUtils.print_info(String.format("Success Convert Audio Format: %s -> %s", rawPath, newPath)); return newPath; } catch (IOException e) { //e.printStackTrace(); CommonUtils.print_info(String.format("Audio Format Convert Error: %s -> %s", rawPath, e.getMessage())); return null; } }
//获取媒体音频格式 private static AudioFormat getAudioFormat(String fileName){ // AudioFormat rawFormat = AudioSystem.getAudioFileFormat(new File(fileName)).getFormat(); try { InputStream inputStream = FileUtil.JarReadFileStream(fileName); AudioFormat audioFormat = AudioSystem.getAudioInputStream(new BufferedInputStream(inputStream)).getFormat(); return audioFormat; } catch (UnsupportedAudioFileException e) { CommonUtils.print_error(String.format("%s -> %s", fileName, e.getMessage())); } catch (IOException e) { CommonUtils.print_error(String.format("%s -> %s", fileName, e.getMessage())); } return null; }
//获取媒体输入流 private static AudioInputStream getAudioInputStream(String fileName) { try { //AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File(fileName)); InputStream inputStream = FileUtil.JarReadFileStream(fileName); AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new BufferedInputStream(inputStream)); return audioInputStream; } catch (IOException e) { CommonUtils.print_error(String.format("%s -> %s", fileName, e.getMessage())); } catch (UnsupportedAudioFileException e) { CommonUtils.print_error(String.format("%s -> %s", fileName, e.getMessage())); } return null; }
//自动检测音乐是否能够播放 private static String checkAndConvert(String fileName, boolean overlay) { //判断文件是否可以播放,不可以播放进行格式转换 java11时isSupportedAudioFormat错误 if(isSupportedFormat(fileName)){ return fileName; }
//进行格式转换修复
//从原始文件中获取 sampleRate float sampleRate = 16000 ; AudioFormat rawFormat = getAudioFormat(fileName); if (rawFormat != null){ sampleRate = rawFormat.getSampleRate(); }
//获取本系统支持的格式 String[] defaultOP = defaultFormatString.split("<->",3); AudioFormat.Encoding targetEncoding = new AudioFormat.Encoding(defaultOP[0]); int sampleSizeInBits = Integer.parseInt(defaultOP[1]); int channels = Integer.parseInt(defaultOP[2]);
// 目标音频格式 AudioFormat newAudioFormat = new AudioFormat(targetEncoding, sampleRate, sampleSizeInBits, channels, (sampleSizeInBits / 8) * channels, sampleRate, false);
//生成新的文件 if (overlay){ fileName = convertFormat(fileName, fileName, newAudioFormat); }else { fileName = convertFormat(fileName, fileName+".new.wav", newAudioFormat); }
//检查新的文件是否可以播放 if(!CommonUtils.isNullOrEmpty(fileName) && isSupportedFormat(fileName)){ CommonUtils.print_info(String.format("Converted Audio Supported: [%s]", fileName)); return fileName; }
return null; }
//播放音频 private static boolean simplePlayAudio(String fileName) { try { // 获取音频输入流 AudioInputStream audioInputStream = getAudioInputStream(fileName);
AudioFormat audioFormat = audioInputStream.getFormat(); CommonUtils.print_info(String.format("Audio Info: [%s] -> Encoding: [%s]", fileName, audioFormat.toString())); DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, audioFormat); SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
sourceDataLine.open(); sourceDataLine.start();
byte buf[] = new byte[0xFF]; int len; while ((len = audioInputStream.read(buf, 0, buf.length)) != -1) { sourceDataLine.write(buf, 0, len); } sourceDataLine.drain(); sourceDataLine.close(); audioInputStream.close(); return true; } catch (Exception e) { //e.printStackTrace(); CommonUtils.print_info(String.format("%s Play Error", fileName)); return false; }finally { playing = false; } }
//自动检测并播放音频 public static void checkAndPlayAudio(String fileName, boolean overlay) { if (playing || null == audioPlayer || CommonUtils.isNullOrEmpty(defaultFormatString) ) { CommonUtils.print_error("Player is Not Init Or Player is Using, Skip!!!"); return; }
//独占模式 每次只播放一个音频 playing = true;
//检查和自动修复wav格式问题 fileName = checkAndConvert(fileName, overlay);
if (CommonUtils.isNullOrEmpty(fileName)){ CommonUtils.print_error(String.format("Audio Check And Convert Not Passed: [%s]", fileName)); return; } //进行播放测试 simplePlayAudio(fileName); }

public static void checkAndPlayAudio(String event){ CommonUtils.print_info(String.format("Play Audio By [%s]", event)); new Thread(() -> { checkAndPlayAudio("resources/audio.wav",true); }).start(); }
public static void main(String[] args) throws UnsupportedEncodingException { //无法播放的类型 String wav_2 = "C:/Users/XXX/Desktop/Audio.wav"; //获取实例 AudioPlayer.initInstance(); AudioPlayer.checkAndPlayAudio(wav_2,false); }}
0x03 寻找信号接收点
使用的方法比较傻,没有调试客户端,而是利用上线时会有一条日志消息显示[beacon_initial from xxxx],如果能找到这个消息的来源,并进行判断,就能够实现Beacon上线通知
最终进过关键字查找和回溯函数调用,找到DataManager.java文件result函数,具体实现代码如下:
      if (!(obj instanceof Directive)) {         if (!this.syncing) {            if (obj instanceof Scriptable) {               Scriptable scriptable = (Scriptable)obj;               String eventName = scriptable.eventName();               Stack arguments = scriptable.eventArguments();               this.engine.getEventManager().fireEvent(eventName, arguments);
//添加初始化上线响铃操作 if("beacon_initial".equals(eventName.trim())) AudioPlayer.checkAndPlayAudio(eventName);            }            ...省略
0x04 总结
本文最有用的的地方大概就是[知道信号通知可以在哪里判断],后续添加其他功能都可以在这里进行修改
对于想要语音提示[您的冤种已上线]还是[您的主机已上线]这样的功能,只需要使用文本转语音的功能生成音频文件,然后替换wav文件即可.
编译后的文件已整理完毕,将下一篇文章进行分享.
其中的重要更新内容:
1、修改JARM/JA3 指纹[通过随机化https算法]2、支持初次上线铃声通知3、无需javaAgent完善修复XSS RCE漏洞
PS:所有代码依旧 保留Java8级别的兼容性.
感谢大家的关注和支持.
0x99 免责声明

在学习本文技术或工具使用前,请您务必审慎阅读、充分理解各条款内容。

1、本团队分享的任何类型技术、工具文章等文章仅面向合法授权的企业安全建设行为与个人学习行为,严禁任何组织或个人使用本团队技术或工具进行非法活动。

2、在使用本文相关工具及技术进行测试时,您应确保该行为符合当地的法律法规,并且已经取得了足够的授权。如您仅需要测试技术或工具的可行性,建议请自行搭建靶机环境,请勿对非授权目标进行扫描。

3、如您在使用本工具的过程中存在任何非法行为,您需自行承担相应后果,我们将不承担任何法律及连带责任。

4、本团队目前未发起任何对外公开培训项目和其他对外收费项目,严禁任何组织或个人使用本团队名义进行非法盈利。

5、本团队所有分享工具及技术文章,严禁不经过授权的公开分享。

如果发现上述禁止行为,我们将保留追究您法律责任的权利,并由您自身承担由禁止行为造成的任何后果。

END

如您有任何投稿、问题、建议、需求、合作、后台留言NOVASEC公众号!

或添加NOVASEC-酒零 以便于及时回复。

感谢大哥们的对NOVASEC的支持点赞和关注

加入我们与萌新一起成长吧!

本团队任何技术及文件仅用于学习分享,请勿用于任何违法活动,感谢大家的支持!


文章来源: https://mp.weixin.qq.com/s?__biz=MzUzODU3ODA0MA==&mid=2247489134&idx=1&sn=114252d1e14a9cbf5f39bb1b89ffc7a4&chksm=fad4cb79cda3426f63d7488e6c9ade56182c3ba01e7b0f4159f2d0eb24a8dc1a588638aeeed7&scene=58&subscene=0#rd
如有侵权请联系:admin#unsafe.sh