Commit f3b4df34 by 钱炳权

纯净版后端

parent 28c5934d
......@@ -17,73 +17,18 @@
<java.version>11</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-cloud.version>2021.0.5</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version>
</properties>
<dependencies>
<!-- 微服务依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>3.1.5</version>
</dependency>
<!-- springCloud相关-->
<!-- SpringCloud依赖开始-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.1.2</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2021.0.5.0</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<version>3.1.5</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2021.0.5.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.9</version>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.31</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>2.7.2</version>
</dependency>
<!-- log4j - slf4j 日志依赖 结束-->
<dependency>
<groupId>com.fasterxml.uuid</groupId>
......@@ -96,23 +41,6 @@
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
<!--WebSocket核心依赖包-->
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.3.8</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--PageHelper-->
<dependency>
<groupId>com.github.pagehelper</groupId>
......@@ -120,17 +48,6 @@
<version>1.4.6</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
......
......@@ -2,12 +2,11 @@ package com.example.fuzzControll;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import java.util.Arrays;
@SpringBootApplication
@EnableFeignClients
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class FuzzIntegration {
public static void main(String[] args) {
Arrays.stream(args).forEach(System.out::println);
......
package com.example.fuzzControll.conf;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component("IntegrationPathProperties")
@ConfigurationProperties(prefix = "integrationpath")
public class IntegrationPathProperties {
String webSocketUri;
public String getWebSocketUri() {
return webSocketUri;
}
public void setWebSocketUri(String webSocketUri) {
this.webSocketUri = webSocketUri;
}
}
package com.example.fuzzControll.conf;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component("kittyProperties")
@ConfigurationProperties(prefix = "kitty")
public class KittyProperties {
String logOutPath;
String path;
String venvPath;
String methodPath;
String vulnerabilityTypePath;
String templateInfoHttp;
String statsHttp;
String stagesHttp;
String reportHttp;
String mutationPath;
public String getLogOutPath() {
return logOutPath;
}
public void setLogOutPath(String logOutPath) {
this.logOutPath = logOutPath;
}
public String getMutationPath() {
return mutationPath;
}
public void setMutationPath(String mutationPath) {
this.mutationPath = mutationPath;
}
public String getTemplateInfoHttp() {
return templateInfoHttp;
}
public void setTemplateInfoHttp(String templateInfoHttp) {
this.templateInfoHttp = templateInfoHttp;
}
public String getStatsHttp() {
return statsHttp;
}
public void setStatsHttp(String statsHttp) {
this.statsHttp = statsHttp;
}
public String getStagesHttp() {
return stagesHttp;
}
public void setStagesHttp(String stagesHttp) {
this.stagesHttp = stagesHttp;
}
public String getReportHttp() {
return reportHttp;
}
public void setReportHttp(String reportHttp) {
this.reportHttp = reportHttp;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getVenvPath() {
return venvPath;
}
public void setVenvPath(String venvPath) {
this.venvPath = venvPath;
}
public String getMethodPath() {
return methodPath;
}
public void setMethodPath(String methodPath) {
this.methodPath = methodPath;
}
public String getVulnerabilityTypePath() {
return vulnerabilityTypePath;
}
public void setVulnerabilityTypePath(String vulnerabilityTypePath) {
this.vulnerabilityTypePath = vulnerabilityTypePath;
}
}
package com.example.fuzzControll.constents;
import com.example.fuzzControll.conf.SpringContextUtil;
import com.example.fuzzControll.conf.KittyProperties;
import com.example.fuzzControll.tools.GlobalParameters;
public class CmdConstent {
......
package com.example.fuzzControll.constents;
public class MutationConstent {
public static final String TEST_GRANULARITY_BIT_BYTE = "test_granularity_bit_byte.py ";
public static final String TEST_MUTATED_LIBS = "test_mutated_libs.py ";
public static final String TEST_MUTATION_STRATEGY = "test_mutation_strategy.py ";
}
package com.example.fuzzControll.constents;
public class ProtocolConstent {
public static final String ARP = "arp_raw.py ";
public static final String BGP = "bgp_tcp.py ";
public static final String DHCP = "dhcp_scapy.py ";
public static final String DNS = "dns_scapy.py ";
public static final String FRP = "frp_udp.py ";
public static final String FTP = "ftp_raw.py ";
public static final String HDLC = "hdlc_raw.py ";
public static final String HTTP_DOS_QUMU = "http_dos_qemu.py ";
public static final String ICMP = "icmp_raw.py ";
public static final String IGMPV1 = "igmpv1_raw.py ";
public static final String IGMPV2 = "igmpv2_raw.py ";
public static final String IMAP = "imap_tcp.py ";
public static final String RADIUS = "radius_udp.py ";
public static final String SIP = "sip_raw.py ";
public static final String RPC = "rpc_udp.py ";
public static final String SSL = "ssl_raw.py ";
public static final String SSH = "ssh_raw.py ";
public static final String NFS = "nfs_tcp.py ";
public static final String NNTP = "nntp_tcp.py ";
public static final String NTP = "ntp_scapy.py ";
public static final String SNMP = "snmp_udp.py ";
public static final String UPNP = "upnp_tcp.py ";
public static final String RARP = "rarp_raw.py ";
public static final String LLDP = "lldp_raw.py ";
public static final String MSTP = "mstp_raw.py ";
public static final String PPP = "ppp_raw.py ";
public static final String PPPOE = "pppoe_raw.py ";
public static final String STP = "stp_raw.py ";
public static final String VLAN = "vlan_raw.py ";
public static final String OSPF = "ospf_raw.py ";
public static final String ISIS = "isis_raw.py ";
public static final String IP = "ip_raw.py ";
public static final String TELNET = "telnet_tcp.py ";
public static final String POP3 = "pop_tcp.py ";
public static final String IPSEC = "ipsec_raw.py ";
public static final String HTTPS = "https_raw.py ";
public static final String RIP = "rip_raw.py ";
public static final String NETBIOS = "netbios_nbns_udp.py ";
public static final String SHARP = "sharp_udp.py ";
public static final String TFTP = "tftp_scapy_field.py ";
public static final String UDP = "udp_raw.py ";
public static final String TCP = "tcp_raw.py ";
public static final String NTF = "ntf_udp.py ";
public static final String RIPNG = "ripng_udp.py ";
public static final String RSTP = "rstp_raw.py ";
public static final String SMTP = "smtp_tcp.py ";
public static final String TIRP = "tirp_udp.py ";
}
package com.example.fuzzControll.constents;
public enum TableClassEnum {
AFLNET("alfnetResult",1),
KITTY_PACKAGE("kittyPackageFile",2),
KITTY_RESULT("kittyResult",3);
private String tableName;
private int tableId;
private TableClassEnum(String tableName, int tableId) {
this.tableName = tableName;
this.tableId = tableId;
}
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public int getTableId() {
return tableId;
}
public void setTableId(int tableId) {
this.tableId = tableId;
}
}
......@@ -3,7 +3,6 @@ package com.example.fuzzControll.controller;
import com.example.fuzzControll.exception.AflnetException;
import com.example.fuzzControll.exception.BaseException;
import com.example.fuzzControll.exception.CmdException;
import com.example.fuzzControll.exception.MysqlException;
import com.example.fuzzControll.pojo.vo.AjaxResult;
import com.example.fuzzControll.pojo.vo.CmdStartParams;
import com.example.fuzzControll.service.TestService;
......@@ -20,7 +19,7 @@ import org.springframework.web.bind.annotation.RestController;
*/
@Slf4j
@RestController
@RequestMapping("/test")
@RequestMapping("/aflnet")
public class AlfnetController {
@Autowired
TestService service;
......@@ -32,7 +31,6 @@ public class AlfnetController {
public AjaxResult start(@RequestBody final CmdStartParams cmdStartParams) {
//todo 捕获子线程错误
try {
GlobalParameters.aflnetData.put("missionName", cmdStartParams.getProtopcol());
new Thread(new Runnable() {
@Override
public void run() {
......@@ -58,10 +56,8 @@ public class AlfnetController {
} catch (AflnetException e) {
log.error(e.getDefaultMessage());
return AjaxResult.error("测试停止失败!");
} catch (MysqlException e){
log.error("File backup error: " + e.getMessage());
}
return AjaxResult.success("测试停止成功!");
}
}
}
\ No newline at end of file
package com.example.fuzzControll.controller;
import com.example.fuzzControll.exception.CmdException;
import com.example.fuzzControll.exception.FuzzException;
import com.example.fuzzControll.pojo.vo.AjaxResult;
import com.example.fuzzControll.pojo.vo.TestEntity;
import com.example.fuzzControll.service.GenerateMethodService;
import com.example.fuzzControll.service.MutationService;
import com.example.fuzzControll.service.ProtocolTemplateService;
import com.example.fuzzControll.service.VulnerabilityTypeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
/**
* 不同类型的测试方法
*/
@Slf4j
@RestController
@RequestMapping("/testClass")
public class KittyController {
@Autowired
GenerateMethodService generateMethodService;
@Autowired
MutationService mutationService;
@Autowired
ProtocolTemplateService protocolTemplateService;
@Autowired
VulnerabilityTypeService vulnerabilityTypeService;
/**
* 模板
*/
@RequestMapping(value = "/protocolTemplate", method = RequestMethod.POST)
public AjaxResult protocolTemplate(@RequestBody TestEntity testEntity) {
try {//todo missionId
Map<String, List<String>> result = protocolTemplateService.generation(testEntity,1);
return AjaxResult.success(result == null ? "模板文件生成未成功运行!第三方接口可能存在问题。" : result);
} catch (CmdException | FuzzException e) {
log.error(e.getDefaultMessage());
return AjaxResult.error("模板生成失败!系统存在问题。");
}
}
/**
* 生成方法
*/
@RequestMapping(value = "/generate", method = RequestMethod.POST)
public AjaxResult generate(@RequestBody TestEntity testEntity) {
try {
//todo 需要传入missionId
Map<String, List<String>> result = generateMethodService.generation(testEntity,1);
return AjaxResult.success(result == null ? "生成方法未成功运行!第三方接口可能存在问题。" : result);
} catch (CmdException | FuzzException e) {
log.error(e.getDefaultMessage());
return AjaxResult.error("生成方法使用失败!系统存在问题。");
}
}
/**
* 变异方法
*/
@RequestMapping(value = "/mutation", method = RequestMethod.POST)
public AjaxResult mutation(@RequestBody TestEntity testEntity) {
try {
Map<String, List<String>> result = mutationService.generation(testEntity,1);
return AjaxResult.success(result == null ? "mutationTest未成功运行!第三方接口可能存在问题。" : result);
} catch (CmdException | FuzzException e) {
log.error(e.getDefaultMessage());
return AjaxResult.error("mutationTest失败!系统存在问题。");
}
}
/**
* 漏洞类型
*/
@RequestMapping(value = "/vulnerabilityType", method = RequestMethod.POST)
public AjaxResult vulnerability(@RequestBody TestEntity testEntity) {
try {
Map<String, List<String>> result = vulnerabilityTypeService.generation(testEntity,1);
return AjaxResult.success(result == null ? "漏洞类型未成功运行!第三方接口可能存在问题。" : result);
} catch (CmdException | FuzzException e) {
log.error(e.getDefaultMessage());
return AjaxResult.error("漏洞类型测试失败!系统存在问题。");
}
}
}
package com.example.fuzzControll.controller;
import com.alibaba.fastjson.JSON;
import com.example.fuzzControll.exception.ServerException;
import com.example.fuzzControll.pojo.vo.AjaxResult;
import com.example.fuzzControll.service.GetServerMessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;
/**
* kitty服务器信息
*/
@RestController
@RequestMapping("/kittyServer")
@Slf4j
public class KittyServerMessageController {
@Autowired
GetServerMessageService getServerMessageService;
/**
* 获取服务器stats信息
*/
@RequestMapping(value = "/stats", method = RequestMethod.GET)
public AjaxResult getStats( ) {
try {
return AjaxResult.success(JSON.parse(getServerMessageService.getStats()));
} catch (ServerException e) {
log.error(e.getDefaultMessage());
return AjaxResult.error("stats信息获取失败!");
}
}
/**
* 获取服务器templateInfo信息
*/
@RequestMapping(value = "/templateInfo", method = RequestMethod.GET)
public AjaxResult getTemplateInfo( ) {
try {
return AjaxResult.success(JSON.parse(getServerMessageService.getTemplateInfo()));
} catch (ServerException e) {
log.error(e.getDefaultMessage());
return AjaxResult.error("templateInfo信息获取失败!");
}
}
/**
* 获取服务器stages信息
*/
@RequestMapping(value = "/stages", method = RequestMethod.GET)
public AjaxResult getStages( ) {
try {
return AjaxResult.success(JSON.parse(getServerMessageService.getStages()));
} catch (ServerException e) {
log.error(e.getDefaultMessage());
return AjaxResult.error("stages信息获取失败!");
}
}
/**
* 获取服务器report信息
*/
@RequestMapping(value = "/report", method = RequestMethod.GET)
public AjaxResult getReport( ) {
try {
return AjaxResult.success(JSON.parse(getServerMessageService.getReport()));
} catch (ServerException e) {
log.error(e.getDefaultMessage());
return AjaxResult.error("report信息获取失败!");
}
}
}
package com.example.fuzzControll.controller;
import com.example.fuzzControll.service.websocketClientService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("/websocket")
public class WebsocketController {
@Autowired
websocketClientService websocketClientService;
@RequestMapping(value = "/connect", method = RequestMethod.GET)
public void connect(){
try {
websocketClientService.connect();
} catch (Exception e) {
e.printStackTrace();
}
log.info("Connect success!");
}
@RequestMapping(value = "/disConnect", method = RequestMethod.GET)
public void disConnect(){
try {
websocketClientService.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
log.info("Disconnect success!");
}
}
package com.example.fuzzControll.controller.dataController;
import com.example.fuzzControll.pojo.vo.AflnetDataParams;
import com.example.fuzzControll.pojo.vo.AjaxResult;
import com.example.fuzzControll.pojo.vo.KittyResult;
import com.example.fuzzControll.service.AflnetPersistenceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/aflnet")
@Slf4j
public class AflnetDataController {
@Autowired
AflnetPersistenceService aflnetPersistenceService;
/**
* 读取数据库文件至指定目录
*/
@RequestMapping(value = "/loadFile", method = RequestMethod.GET)
public AjaxResult AflnetResultSelect(@RequestBody AflnetDataParams aflnetDataParams) {
try {
aflnetPersistenceService.loadInFile(aflnetDataParams.getMissionId(),aflnetDataParams.getFilPath());
} catch (Exception e) {
e.printStackTrace();
return AjaxResult.error("File load failed!");
}
return AjaxResult.success("File loaded successfully!");
}
}
package com.example.fuzzControll.controller.dataController;
import com.example.fuzzControll.pojo.vo.AflnetDataParams;
import com.example.fuzzControll.pojo.vo.AjaxResult;
import com.example.fuzzControll.pojo.vo.FuzzLogTransEntity;
import com.example.fuzzControll.service.FuzzLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@RestController
@RequestMapping("/log")
@Slf4j
public class FuzzLogController {
@Autowired
FuzzLogService FuzzLogService;
/**
* 下载对应任务的日志;不同任务返回数据类型不同,需要做个表来区分
*/
@RequestMapping(value = "/download/{missionId}", method = RequestMethod.GET)
public FuzzLogTransEntity getFuzzLog(@PathVariable("missionId") int missionId) throws IOException {
try {
return FuzzLogService.getFuzzLog(missionId);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
package com.example.fuzzControll.controller.dataController;
import com.example.fuzzControll.pojo.vo.AjaxResult;
import com.example.fuzzControll.pojo.vo.KittyDataParams;
import com.example.fuzzControll.pojo.vo.KittyResult;
import com.example.fuzzControll.service.KittyFuzzPersistenceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/kittyServer")
@Slf4j
public class KittyDataController {
@Autowired
KittyFuzzPersistenceService fuzzPersistenceService;
/**
* 查询kitty结果
*/
@RequestMapping(value = "/KittyResultSelect", method = RequestMethod.GET)
public AjaxResult KittyResultSelect() {
List<KittyResult> results;
try {
results = fuzzPersistenceService.getKittyResults();
} catch (Exception e) {
e.printStackTrace();
return AjaxResult.error();
}
return AjaxResult.success(results);
}
/**
* 查询kittyPackage
*/
@RequestMapping(value = "/kittyPackageFileLoad", method = RequestMethod.POST)
public AjaxResult kittyPackageFileLoad(@RequestBody KittyDataParams kittyDataParams) {
try {
fuzzPersistenceService.loadKittyLogFileInLocal(kittyDataParams);
} catch (Exception e) {
e.printStackTrace();
return AjaxResult.error();
}
return AjaxResult.success("load success!");
}
}
package com.example.fuzzControll.controller.dataController;
import com.example.fuzzControll.mapper.MissionInfoMapper;
import com.example.fuzzControll.pojo.vo.AjaxResult;
import com.example.fuzzControll.pojo.vo.FuzzLogTransEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
@RestController
@RequestMapping("/mission")
@Slf4j
public class MissionInfoController {
@Autowired
MissionInfoMapper missionInfoMapper;
/**
* 查看任务信息
*/
@RequestMapping(value = "/getList", method = RequestMethod.GET)
public AjaxResult getMissionInfo() throws IOException {
try {
return AjaxResult.success(missionInfoMapper.selectMissionInfoList());
} catch (Exception e) {
e.printStackTrace();
return AjaxResult.error("SelectMissionInfoList error!");
}
}
}
package com.example.fuzzControll.exception;
public class MysqlException extends BaseException{
private static final long serialVersionUID = 1L;
public MysqlException(String defaultMessage) {
super(defaultMessage, "mysql");
}
}
package com.example.fuzzControll.exception;
public class ServerException extends BaseException{
private static final long serialVersionUID = 1L;
public ServerException(String defaultMessage) {
super(defaultMessage, "server");
}
}
package com.example.fuzzControll.mapper;
import com.example.fuzzControll.pojo.vo.AflnetResult;
import com.example.fuzzControll.pojo.vo.KittyResult;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;
import java.util.List;
@Mapper
@Component("AflnetMapper")
public interface AflnetMapper {
/**
* 查询kitty模糊测试结果
*/
// List<KittyResult> getKittyResults();
/**
* 存储alfnet测试结果
*/
int aflnetOutputBackup(AflnetResult aflnetResult);
AflnetResult selectResultById(int missionId);
}
package com.example.fuzzControll.mapper;
import com.example.fuzzControll.pojo.vo.KittyResult;
import com.example.fuzzControll.pojo.vo.KittyPackageFile;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;
import java.util.List;
@Mapper
@Component("KittyMapper")
public interface KittyMapper {
/**
* 查询kitty模糊测试结果
*/
List<KittyResult> getKittyResults();
int kittyResultsBackup(KittyResult kittyResult);
int kittyPackagesBackup(KittyPackageFile kittyPackageFile);
KittyPackageFile getKittyPackageFileById(int missionId);
KittyResult getKittyResultByMissionId(int missionId);
/**
* 查询kitty日志
*/
// List<KittyLog> selectByNodeType(int nodeType);
}
package com.example.fuzzControll.mapper;
import com.example.fuzzControll.pojo.vo.MissionInfo;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;
import java.util.List;
@Mapper
@Component("MissionInfoMapper")
public interface MissionInfoMapper {
MissionInfo selectByMissionId(int missionId);
/**
* 查询任务信息列表
*/
List<MissionInfo> selectMissionInfoList();
/**
* 查询当前任务Id
*/
int selectTopMissionId();
void insertMission(MissionInfo missionInfo);
}
package com.example.fuzzControll.pojo.vo;
import lombok.Data;
@Data
public class AflnetDataParams {
private String filPath;
private int missionId;
public AflnetDataParams() {
}
public AflnetDataParams(String filPath, int missionId) {
this.filPath = filPath;
this.missionId = missionId;
}
}
package com.example.fuzzControll.pojo.vo;
import lombok.Data;
@Data
public class FuzzLogTransEntity {
private byte[] file;
private String name;
public FuzzLogTransEntity(byte[] file, String name) {
this.file = file;
this.name = name;
}
public FuzzLogTransEntity() {
}
}
package com.example.fuzzControll.pojo.vo;
import lombok.Data;
@Data
public class KittyDataParams {
private String filPath;
private int missionId;
public KittyDataParams() {
}
public KittyDataParams(String filPath, int missionId) {
this.filPath = filPath;
this.missionId = missionId;
}
}
package com.example.fuzzControll.pojo.vo;
public class KittyLog {
int id;
}
package com.example.fuzzControll.pojo.vo;
import lombok.Data;
@Data
public class KittyPackageFile {
private int id;
private int missionId;
private String kittyRecvFileName;
private String kittySendFileName;
private byte[] kittyRecvFile;
private byte[] kittySendFile;
public KittyPackageFile(int missionId, String kittyRecvFileName, String kittySendFileName, byte[] kittyRecvFile, byte[] kittySendFile) {
this.missionId = missionId;
this.kittyRecvFileName = kittyRecvFileName;
this.kittySendFileName = kittySendFileName;
this.kittyRecvFile = kittyRecvFile;
this.kittySendFile = kittySendFile;
}
@Override
public String toString() {
return "kittyPackageFile{" +
"id=" + id +
", missionId=" + missionId +
", kittyRecvFileName='" + kittyRecvFileName + '\'' +
", kittySendFileName='" + kittySendFileName + '\'' +
", kittyRecvFile=" + kittyRecvFile.length +
", kittySendFile=" +kittySendFile.length +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getMissionId() {
return missionId;
}
public void setMissionId(int missionId) {
this.missionId = missionId;
}
public String getKittyRecvFileName() {
return kittyRecvFileName;
}
public void setKittyRecvFileName(String kittyRecvFileName) {
this.kittyRecvFileName = kittyRecvFileName;
}
public String getKittySendFileName() {
return kittySendFileName;
}
public void setKittySendFileName(String kittySendFileName) {
this.kittySendFileName = kittySendFileName;
}
public byte[] getKittyRecvFile() {
return kittyRecvFile;
}
public void setKittyRecvFile(byte[] kittyRecvFile) {
this.kittyRecvFile = kittyRecvFile;
}
public byte[] getKittySendFile() {
return kittySendFile;
}
public void setKittySendFile(byte[] kittySendFile) {
this.kittySendFile = kittySendFile;
}
}
package com.example.fuzzControll.pojo.vo;
import lombok.Data;
@Data
public class KittyResult {
private int id;
private int missionId;
private String resultOut;
private String resultError;
public KittyResult() {
}
public KittyResult(int missionId, String resultOut, String resultError) {
this.missionId = missionId;
this.resultOut = resultOut;
this.resultError = resultError;
}
}
package com.example.fuzzControll.pojo.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import java.util.Date;
@Data
public class MissionInfo {
@JsonIgnore
private int id;
private int missionId;
@JsonIgnore
private int tableId;//返回数据忽略字段
private Date createTime;
private String missionName;
public MissionInfo() {
}
public MissionInfo(int id, int missionId, int tableId, Date createTime, String missionName) {
this.id = id;
this.missionId = missionId;
this.tableId = tableId;
this.createTime = createTime;
this.missionName = missionName;
}
public MissionInfo(int missionId, int tableId, Date createTime, String missionName) {
this.missionId = missionId;
this.tableId = tableId;
this.createTime = createTime;
this.missionName = missionName;
}
}
package com.example.fuzzControll.pojo.vo;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
@Data
@Getter
@Setter
public class TestEntity {
String testClassName;
String[] paramJson;
}
package com.example.fuzzControll.pojo.vo;
import lombok.Data;
@Data
public class TestReturnEntity {
String run_time;
String cycles_done;
String last_new_path;
String total_paths;
String last_uniq_crash;
String uniq_crashes;
String last_uniq_hang;
String uniq_hangs;
String now_processing;
String map_density;
String paths_timed_out;
String count_coverage;
String now_trying;
String favored_paths;
String stage_execs;
String new_edges_on;
String total_execs;
String total_crashes;
String exec_speed;
String total_tmouts;
String bit_flips;
String levels;
String byte_flips;
String pending;
String arithmetics;
String pend_fav;
String known_ints;
String own_finds;
String dictionary;
String imported;
String havoc;
String stability;
String trim;
}
package com.example.fuzzControll.service;
public interface AflnetPersistenceService {
public int aflnetResultBackup(String filename,String missionName);
public void loadInFile(int missionId,String filePath);
}
package com.example.fuzzControll.service;
import com.example.fuzzControll.pojo.vo.FuzzLogTransEntity;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface FuzzLogService {
FuzzLogTransEntity getFuzzLog(int missionId) throws IllegalAccessException;
}
package com.example.fuzzControll.service;
import com.example.fuzzControll.pojo.vo.TestEntity;
import java.util.List;
import java.util.Map;
public interface GenerateMethodService {
Map<String,List<String>> generation(TestEntity testEntity,int missionId);
}
package com.example.fuzzControll.service;
public interface GetServerMessageService {
String getStats();
String getTemplateInfo();
String getStages();
String getReport();
}
package com.example.fuzzControll.service;
import com.example.fuzzControll.pojo.vo.KittyDataParams;
import com.example.fuzzControll.pojo.vo.KittyResult;
import java.util.List;
public interface KittyFuzzPersistenceService {
List<KittyResult> getKittyResults();
public int KittyPackagesBackup(int missionId);
public int kittyResultsBackup(KittyResult kittyResult);
void loadKittyLogFileInLocal(KittyDataParams kittyDataParams);
}
package com.example.fuzzControll.service;
import com.example.fuzzControll.pojo.vo.TestEntity;
import java.util.List;
import java.util.Map;
public interface MutationService {
Map<String, List<String>> generation(TestEntity testEntity,int missionId);
}
package com.example.fuzzControll.service;
import com.example.fuzzControll.pojo.vo.TestEntity;
import java.util.List;
import java.util.Map;
public interface ProtocolTemplateService {
Map<String,List<String>> generation(TestEntity testEntity,int missionId);
}
......@@ -7,10 +7,12 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.ReentrantLock;
public interface SeedFileService {
public List<String> getSeedFiles();
void delFile(String fileName);
void upload(MultipartFile file) ;
int getSeedFileCount(String msg );
}
package com.example.fuzzControll.service;
import com.example.fuzzControll.pojo.vo.TestEntity;
import java.util.List;
import java.util.Map;
public interface VulnerabilityTypeService {
Map<String, List<String>> generation(TestEntity testEntity,int missionId);
}
package com.example.fuzzControll.service.impl;
import com.example.fuzzControll.conf.AflnetProperties;
import com.example.fuzzControll.constents.TableClassEnum;
import com.example.fuzzControll.exception.MysqlException;
import com.example.fuzzControll.mapper.AflnetMapper;
import com.example.fuzzControll.mapper.MissionInfoMapper;
import com.example.fuzzControll.pojo.vo.AflnetResult;
import com.example.fuzzControll.pojo.vo.KittyResult;
import com.example.fuzzControll.pojo.vo.MissionInfo;
import com.example.fuzzControll.service.AflnetPersistenceService;
import com.example.fuzzControll.tools.FileTools;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
@Slf4j
@Service("AflnetPersistenceService")
public class AflnetPersistenceServiceImpl implements AflnetPersistenceService {
@Autowired
AflnetMapper aflnetMapper;
@Autowired
AflnetProperties aflnetProperties;
@Autowired
MissionInfoMapper missionInfoMapper;
FileTools fileTools = new FileTools();
@Override
public int aflnetResultBackup(String filename, String missionName) {
return mysqlTransaction(filename, missionName);
}
@Override
public void loadInFile(int missionId, String filePath) {
AflnetResult aflnetResult = null;
try {
aflnetResult = aflnetMapper.selectResultById(missionId);
} catch (MysqlException e) {
e.printStackTrace();
throw new MysqlException("AflnetMapper.selectResultById() Error!");
}
fileTools.loadFileInLocal(filePath, aflnetResult.getFileName(), aflnetResult.getFile());
}
@Transactional(rollbackFor = MysqlException.class)
public int mysqlTransaction(String filename,String missionName) {
int topMissionId = missionInfoMapper.selectTopMissionId() + 1;//获取最新的missionId
AflnetResult result = new AflnetResult(topMissionId, fileTools.fileReadAndTranstoBytes(aflnetProperties.getOutputPath(), filename), filename);
aflnetMapper.aflnetOutputBackup(result);//存入日志文件
missionInfoMapper.insertMission(new MissionInfo(topMissionId, TableClassEnum.AFLNET.getTableId(), new Date(), missionName));//插入任务信息
return 1;
}
}
package com.example.fuzzControll.service.impl;
import com.example.fuzzControll.mapper.AflnetMapper;
import com.example.fuzzControll.mapper.KittyMapper;
import com.example.fuzzControll.mapper.MissionInfoMapper;
import com.example.fuzzControll.pojo.vo.AflnetResult;
import com.example.fuzzControll.pojo.vo.FuzzLogTransEntity;
import com.example.fuzzControll.pojo.vo.KittyResult;
import com.example.fuzzControll.pojo.vo.MissionInfo;
import com.example.fuzzControll.service.FuzzLogService;
import com.example.fuzzControll.tools.FileTools;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Slf4j
@Service("FuzzLogService")
public class FuzzLogServiceImpl implements FuzzLogService {
@Autowired
MissionInfoMapper missionInfoMapper;
@Autowired
AflnetMapper aflnetMapper;
@Autowired
KittyMapper kittyMapper;
FileTools fileTools = new FileTools();
@Override
public FuzzLogTransEntity getFuzzLog(int missionId) throws IllegalAccessException {
MissionInfo missionInfo = missionInfoMapper.selectByMissionId(missionId);
if (missionInfo == null) {
return null;
}
switch (missionInfo.getTableId()) {
case 1:
return downloadAflnetFile(missionInfo);
// case 2:return downloadKittyProtocalFile(missionInfo);
case 3:
return downloadKittyOtherMethodFile(missionInfo);
default:
throw new IllegalAccessException("Invalid mission!");
}
}
private FuzzLogTransEntity downloadKittyOtherMethodFile(MissionInfo missionInfo) {
KittyResult kittyResult = kittyMapper.getKittyResultByMissionId(missionInfo.getMissionId());
StringBuffer buffer = new StringBuffer();
buffer.append(kittyResult.getResultError()).append(System.lineSeparator()).append(kittyResult.getResultOut());
return new FuzzLogTransEntity(buffer.toString().getBytes(), missionInfo.getMissionName()+".txt");
}
private FuzzLogTransEntity downloadAflnetFile(MissionInfo missionInfo) {
AflnetResult aflnetResult = aflnetMapper.selectResultById(missionInfo.getMissionId());
return new FuzzLogTransEntity(aflnetResult.getFile(), aflnetResult.getFileName());
}
}
package com.example.fuzzControll.service.impl;
import com.example.fuzzControll.conf.KittyProperties;
import com.example.fuzzControll.exception.CmdException;
import com.example.fuzzControll.exception.FuzzException;
import com.example.fuzzControll.pojo.vo.TestEntity;
import com.example.fuzzControll.service.GenerateMethodService;
import com.example.fuzzControll.tools.CmdTools;
import com.example.fuzzControll.tools.TestTools;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
@Service
@Slf4j
public class GenerateMethodServiceImpl implements GenerateMethodService {
CmdTools cmdTools = new CmdTools();
@Autowired
KittyProperties kitty;
@Override
public Map<String, List<String>> generation(TestEntity testEntity,int missionId) throws FuzzException, CmdException {
String cmd = parseParameters(testEntity);
if (cmd.isEmpty()) {
throw new FuzzException("cmd is null ! The number of parameters does not match!");
}
return cmdTools.runProgramCmdAndResult(cmd,"generate","Generate-"+testEntity.getTestClassName());
}
public String parseParameters(TestEntity testEntity) {
try {
switch (testEntity.getTestClassName().toLowerCase()) {
case "foreach":
return cmd(testEntity, "-f");
case "repeat":
return cmd(testEntity, "-r");
case "oneof":
return cmd(testEntity, "-o");
case "switch":
return cmd(testEntity, "-s");
case "pad":
return cmd(testEntity, "-p");
case "template":
return cmd(testEntity, "-t");
case "meta":
return cmd(testEntity, "-m");
case "if":
return cmd(testEntity, "-c");
case "ifnot":
return cmd(testEntity, "-e");
case "trunc"://have error
return cmd(testEntity, "-u");
default:
throw new FuzzException("Unknown method !");
}
} catch (FuzzException e) {
throw new FuzzException("Unknown method !");
}
}
private String cmd(TestEntity testEntity, String cmd) throws FuzzException {
if (!TestTools.paramsLenghtTest(testEntity.getParamJson().length, 5, "generationMethod"))
return "";
String target_host = null;
String target_port = null;
String s1 = null;
String s2 = null;
String s3 = null;
try {
target_host = testEntity.getParamJson()[0];
target_port = testEntity.getParamJson()[1];
s1 = testEntity.getParamJson()[2];
s2 = testEntity.getParamJson()[3];
s3 = testEntity.getParamJson()[4];
} catch (Exception e) {
throw new FuzzException("Parameter parsing failed !");
}
return kitty.getVenvPath() + " " + kitty.getMethodPath() + "generate_method_test.py " + cmd + " " + s1 + " " + s2 + " " + s3 + " --host=" + target_host + " --port=" + target_port;
}
}
package com.example.fuzzControll.service.impl;
import com.example.fuzzControll.conf.KittyProperties;
import com.example.fuzzControll.exception.ServerException;
import com.example.fuzzControll.service.GetServerMessageService;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Slf4j
@Service("getServerMessageService")
public class GetServerMessageImpl implements GetServerMessageService {
@Autowired
KittyProperties kitty;
public String getServerMsg(String messageName) {
switch (messageName) {
case "templateInfo": {
HttpGet httpGetTemplateInfo = new HttpGet(kitty.getTemplateInfoHttp());
try (CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse templateInfoResponse = httpClient.execute(httpGetTemplateInfo);) {
return EntityUtils.toString(templateInfoResponse.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
throw new ServerException("get server templateInfo error !");
}
}
case "stats": {
HttpGet httpGetStats = new HttpGet(kitty.getStatsHttp());
try (CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse statsResponse = httpClient.execute(httpGetStats);) {
return EntityUtils.toString(statsResponse.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
throw new ServerException("get server stats error !");
}
}
case "report": {
HttpGet httpGetStats = new HttpGet(kitty.getReportHttp());
try (CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse reportResponse = httpClient.execute(httpGetStats);) {
return EntityUtils.toString(reportResponse.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
throw new ServerException("get server report error !");
}
}
case "stages": {
HttpGet httpGetStats = new HttpGet(kitty.getStagesHttp());
try (CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse stagesResponse = httpClient.execute(httpGetStats);) {
return EntityUtils.toString(stagesResponse.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
throw new ServerException("get server stages error !");
}
}
default:
return "";
}
}
@Override
public String getStats() {
return getServerMsg("stats");
}
@Override
public String getTemplateInfo() throws ServerException{
return getServerMsg("templateInfo");
}
@Override
public String getStages() throws ServerException{
return getServerMsg("stages");
}
@Override
public String getReport() throws ServerException{
return getServerMsg("report");
}
}
package com.example.fuzzControll.service.impl;
import com.example.fuzzControll.conf.KittyProperties;
import com.example.fuzzControll.constents.CmdConstent;
import com.example.fuzzControll.exception.MysqlException;
import com.example.fuzzControll.mapper.KittyMapper;
import com.example.fuzzControll.pojo.vo.KittyDataParams;
import com.example.fuzzControll.pojo.vo.KittyResult;
import com.example.fuzzControll.pojo.vo.KittyPackageFile;
import com.example.fuzzControll.service.KittyFuzzPersistenceService;
import com.example.fuzzControll.tools.CmdTools;
import com.example.fuzzControll.tools.FileTools;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service("KittyFuzzPersistenceService")
@Slf4j
public class KittyFuzzPersistenceServiceImpl implements KittyFuzzPersistenceService {
@Autowired
KittyMapper kittyMapper;
FileTools fileTools = new FileTools();
CmdTools cmdTools = new CmdTools();
@Autowired
KittyProperties kittyProperties;
@Override
public List<KittyResult> getKittyResults() {
return kittyMapper.getKittyResults();
}
@Override
public int KittyPackagesBackup(int missionId) {
List<String> files = cmdTools.runCmd(CmdConstent.GET_FILE_NAME + kittyProperties.getLogOutPath(), "getKittyLogFiles");
if (files.size() > 3) {
log.error("kittyLogs backup failed!");
}
System.out.println("1");
List<String> logFiles = files.stream().filter(file -> file.contains("pcap")).collect(Collectors.toList());
logFiles.forEach(System.out::println);
//todo 需要传入任务id
KittyPackageFile kittyPackageFile = new KittyPackageFile(1, logFiles.get(0), logFiles.get(1),
fileTools.fileReadAndTranstoBytes(kittyProperties.getLogOutPath(), logFiles.get(0)),
fileTools.fileReadAndTranstoBytes(kittyProperties.getLogOutPath(), logFiles.get(1)));
System.out.println(kittyPackageFile);
System.out.println("2");
return kittyMapper.kittyPackagesBackup(kittyPackageFile);
}
@Override
public int kittyResultsBackup(KittyResult kittyResult) {
return kittyMapper.kittyResultsBackup(kittyResult);
}
@Override
public void loadKittyLogFileInLocal(KittyDataParams kittyDataParams) {
KittyPackageFile kittyPackageFile = null;
try {
kittyPackageFile = kittyMapper.getKittyPackageFileById(kittyDataParams.getMissionId());
} catch (MysqlException e) {
e.printStackTrace();
throw new MysqlException("KittyMapper.getKittyPackageFileById Error!");
}
fileTools.loadFileInLocal(kittyDataParams.getFilPath(), kittyPackageFile.getKittyRecvFileName(),kittyPackageFile.getKittyRecvFile());
fileTools.loadFileInLocal(kittyDataParams.getFilPath(), kittyPackageFile.getKittySendFileName(),kittyPackageFile.getKittySendFile());
}
}
package com.example.fuzzControll.service.impl;
import com.example.fuzzControll.conf.KittyProperties;
import com.example.fuzzControll.constents.MutationConstent;
import com.example.fuzzControll.exception.CmdException;
import com.example.fuzzControll.exception.FuzzException;
import com.example.fuzzControll.pojo.vo.TestEntity;
import com.example.fuzzControll.service.MutationService;
import com.example.fuzzControll.tools.CmdTools;
import com.example.fuzzControll.tools.TestTools;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
@Service("mutationService")
@Slf4j
class MutationServiceImpl implements MutationService {
CmdTools cmdTools = new CmdTools();
@Autowired
KittyProperties kitty;
@Override
public Map<String, List<String>> generation(TestEntity testEntity,int missionId) throws FuzzException, CmdException {
String cmd = parseParameters(testEntity);
if (cmd.isEmpty()) {
throw new FuzzException("cmd is null ! The number of parameters does not match!");
}
return cmdTools.runProgramCmdAndResult(cmd,"mutation","Mutation-"+testEntity.getTestClassName());
}
public String parseParameters(TestEntity testEntity) {
try {
switch (testEntity.getTestClassName().toLowerCase()) {
case "bit":
return variationGranularityCmd(testEntity, 1);
case "byte":
return variationGranularityCmd(testEntity, 2);
case "sqlinjection":
return distortionLibCmd(testEntity, 2);
case "commandinjection":
return distortionLibCmd(testEntity, 1);
case "outofbuffer":
return distortionLibCmd(testEntity, 3);
case "directorytraversal":
return distortionLibCmd(testEntity, 4);
case "8-bitinteger":
return distortionLibCmd(testEntity, 5);
case "16-bitinteger":
return distortionLibCmd(testEntity, 6);
case "32-bitinteger":
return distortionLibCmd(testEntity, 7);
case "bitflip":
return mutationStrategyCmd(testEntity, 8);
case "twobitflip":
return mutationStrategyCmd(testEntity, 9);
case "fourbitflip":
return mutationStrategyCmd(testEntity, 10);
case "byteflip":
return mutationStrategyCmd(testEntity, 11);
case "wordflip":
return mutationStrategyCmd(testEntity, 12);
case "dwordflip":
return mutationStrategyCmd(testEntity, 13);
case "blockremove":
return mutationStrategyCmd(testEntity, 14);
case "blockduplicate":
return mutationStrategyCmd(testEntity, 15);
case "blockset":
return mutationStrategyCmd(testEntity, 16);
case "bitflips":
return mutationStrategyCmd(testEntity, 17);
case "byteflips":
return mutationStrategyCmd(testEntity, 1);
case "interestint8muta":
return mutationStrategyCmd(testEntity, 2);
case "interestint16muta":
return mutationStrategyCmd(testEntity, 3);
case "interestint32muta":
return mutationStrategyCmd(testEntity, 4);
case "onebyterndom":
return mutationStrategyCmd(testEntity, 5);
case "mutibytesrandom":
return mutationStrategyCmd(testEntity, 6);
case "deleteonebyterandom":
return mutationStrategyCmd(testEntity, 7);
case "deletemutibytesrandom":
return mutationStrategyCmd(testEntity, 8);
case "shufflebytesrandom":
return mutationStrategyCmd(testEntity, 9);
case "swapadjointwobytes":
return mutationStrategyCmd(testEntity, 10);
default:
throw new FuzzException("Unknown method!");
}
} catch (FuzzException e) {
throw new FuzzException("Count of params is not match or unknown protocol!");
}
}
private String distortionLibCmd(TestEntity testEntity, int methodNum) {
if (!TestTools.paramsLenghtTest(testEntity.getParamJson().length, 2, "distortionLib" + methodNum))
return "";
String dst_ip = null;
String dst_port = null;
try {
dst_ip = testEntity.getParamJson()[0];
dst_port = testEntity.getParamJson()[1];
} catch (Exception e) {
log.error("distortionLib [{}] 参数解析失败!", methodNum);
}
return kitty.getVenvPath() + " " + kitty.getMutationPath() + MutationConstent.TEST_MUTATED_LIBS + " -g " + methodNum + " -d " + dst_ip + " -p " + dst_port;
}
private String variationGranularityCmd(TestEntity testEntity, int methodNum) throws FuzzException {
if (!TestTools.paramsLenghtTest(testEntity.getParamJson().length, 2, "variationGranularity" + methodNum))
return "";
String dst_ip = null;
String dst_port = null;
try {
dst_ip = testEntity.getParamJson()[0];
dst_port = testEntity.getParamJson()[1];
} catch (Exception e) {
throw new FuzzException("Parameter parsing failed !");
}
return kitty.getVenvPath() + " " + kitty.getMutationPath() + MutationConstent.TEST_GRANULARITY_BIT_BYTE + " -g " + methodNum + " -d " + dst_ip + " -p " + dst_port;
}
private String mutationStrategyCmd(TestEntity testEntity, int methodNum) {
if (!TestTools.paramsLenghtTest(testEntity.getParamJson().length, 2, "mutationStrategy" + methodNum))
return "";
String dst_ip = null;
String dst_port = null;
try {
dst_ip = testEntity.getParamJson()[0];
dst_port = testEntity.getParamJson()[1];
} catch (Exception e) {
log.error("mutationStrategy [{}] 参数解析失败!", methodNum);
}
return kitty.getVenvPath() + " " + kitty.getMutationPath() + MutationConstent.TEST_MUTATION_STRATEGY + " -g " + methodNum + " -d " + dst_ip + " -p " + dst_port;
}
}
\ No newline at end of file
......@@ -6,6 +6,7 @@ import com.example.fuzzControll.exception.CmdException;
import com.example.fuzzControll.exception.FileException;
import com.example.fuzzControll.exception.LockException;
import com.example.fuzzControll.service.SeedFileService;
import com.example.fuzzControll.tools.CmdTools;
import com.example.fuzzControll.tools.FileTools;
import lombok.extern.slf4j.Slf4j;
......@@ -22,44 +23,40 @@ import java.util.concurrent.locks.ReentrantLock;
@Service
public class SeedFileServiceImpl implements SeedFileService {
CmdTools cmdTools = new CmdTools();
FileTools fileTools = new FileTools();
@Autowired
AflnetProperties properties;
FileTools fileTools = new FileTools();
@Override
public List<String> getSeedFiles() throws CmdException {
return cmdTools.runCmd(CmdConstent.GET_FILE_NAME + properties.getSeedPath(), "getSeedFiles");
}
//todo 同步修改可能会出现问题
@Override
public void delFile(String fileName) throws CmdException {
public void upload(MultipartFile file) throws FileException, CmdException {
int fileCountBefore = 0;
int fileCountAfter = 0;
fileCountBefore = getSeedFileCount("delFile before.");
cmdTools.runCmd(CmdConstent.DELETE_FILE + properties.getSeedPath() + "/" + fileName, "delFile");
fileCountAfter = getSeedFileCount("delFile after.");
fileCountBefore = getSeedFileCount("upload before.");
fileTools.load(file);
fileCountAfter = getSeedFileCount("upload after.");
if (fileCountAfter == fileCountBefore) {
throw new CmdException("Delete unsuccess ! The file has not changed .Attempt to change permissions or there is no filr to be deleted.");
throw new FileException("upload file error !The file failed to be submitted.Attempt to change permissions.Or thr file has been committed.");
}
}
@Override
public void upload(MultipartFile file) throws FileException, CmdException {
public void delFile(String fileName) throws CmdException {
int fileCountBefore = 0;
int fileCountAfter = 0;
fileCountBefore = getSeedFileCount("upload before.");
fileTools.load(file);
fileCountAfter = getSeedFileCount("upload after.");
fileCountBefore = getSeedFileCount("delFile before.");
cmdTools.runCmd(CmdConstent.DELETE_FILE + properties.getSeedPath() + "/" + fileName, "delFile");
fileCountAfter = getSeedFileCount("delFile after.");
if (fileCountAfter == fileCountBefore) {
throw new FileException("upload file error !The file failed to be submitted.Attempt to change permissions.Or thr file has been committed.");
throw new CmdException("Delete unsuccess ! The file has not changed .Attempt to change permissions or there is no filr to be deleted.");
}
}
/**
* 获取种子文件目录下文件数量
*/
@Override
public int getSeedFileCount(String msg) throws CmdException {
int count = 0;
......@@ -71,4 +68,6 @@ public class SeedFileServiceImpl implements SeedFileService {
}
return count;
}
}
package com.example.fuzzControll.service.impl;
import com.example.fuzzControll.conf.AflnetProperties;
import com.example.fuzzControll.conf.SpringContextUtil;
import com.example.fuzzControll.conf.KittyProperties;
import com.example.fuzzControll.constents.CmdConstent;
import com.example.fuzzControll.exception.AflnetException;
import com.example.fuzzControll.exception.CmdException;
import com.example.fuzzControll.pojo.vo.CmdStartParams;
import com.example.fuzzControll.service.AflnetPersistenceService;
import com.example.fuzzControll.service.TestService;
import com.example.fuzzControll.tools.CmdTools;
import com.example.fuzzControll.tools.GlobalParameters;
......@@ -20,15 +17,12 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CountDownLatch;
@Service("testService")
@Slf4j
public class TestServiceImpl implements TestService {
CmdTools cmdTools = new CmdTools();
@Autowired
AflnetPersistenceService aflnetPersistenceService;
@Autowired
AflnetProperties aflnetProperties;
......@@ -42,7 +36,6 @@ public class TestServiceImpl implements TestService {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss-");
String outputFileName = df.format(date)+cmdStartParams.getProtopcol()+"-output";
String finalCmd = CmdConstent.RUN_AFLNET_BEFORE + outputFileName + CmdConstent.RUN_AFLNET_AFTER + cmd + aflnetProperties.getAflnetPath() + "live555/testProgs/testOnDemandRTSPServer 8554";
GlobalParameters.aflnetData.put("aflnetName", outputFileName);
log.info("The cmd is [{}]",finalCmd);
cmdTools.runProgramCmd(finalCmd, outputFileName + ".zip");
......@@ -53,33 +46,5 @@ public class TestServiceImpl implements TestService {
public void testStop() {
TestControlTools.setIsRunning(false);
log.info("Aflnet has been stopped ! ");
try {
new Thread(new Runnable() {
@Override
public void run() {
int flag = 0;
String fileName = GlobalParameters.aflnetData.get("aflnetName");
String fileZipName = fileName + ".zip";
cmdTools.runCmd(CmdConstent.RUN_ZIP_FILE + fileZipName + " " + fileName, "zip file in testStart");
List<String> files = cmdTools.runCmd(CmdConstent.GET_FILE_NAME + aflnetProperties.getOutputPath(), "getSeedFiles");
while (files.contains(fileZipName) && flag == 0) {//当前存在压缩包才存入
flag = aflnetPersistenceService.aflnetResultBackup(fileZipName,GlobalParameters.aflnetData.get("missionName"));
}
/*清除生成的文件*/
try {
cmdTools.runCmd(CmdConstent.DELETE_FILE+fileName,"delete file");
cmdTools.runCmd(CmdConstent.DELETE_FILE+fileZipName,"delete zipFile");
} catch (CmdException e) {
e.printStackTrace();
log.error("file delete failed!");
}
log.info("kittyLog has been backuped!");
}
}).start();
} catch (Exception e) {
log.error("AflnetBackup Error!");
e.printStackTrace();
}
}
}
package com.example.fuzzControll.service.impl;
import com.example.fuzzControll.conf.KittyProperties;
import com.example.fuzzControll.exception.CmdException;
import com.example.fuzzControll.exception.FuzzException;
import com.example.fuzzControll.pojo.vo.TestEntity;
import com.example.fuzzControll.service.VulnerabilityTypeService;
import com.example.fuzzControll.tools.CmdTools;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
@Slf4j
@Service("vulnerabilityTypeService")
public class VulnerabilityTypeServiceImpl implements VulnerabilityTypeService {
CmdTools cmdTools = new CmdTools();
@Autowired
KittyProperties kitty;
@Override
public Map<String, List<String>> generation(TestEntity testEntity,int missionId) throws FuzzException, CmdException {
String cmd = parseParameters(testEntity);
if (cmd.isEmpty()) {
throw new FuzzException("cmd is null ! The number of parameters does not match!");
}
return cmdTools.runProgramCmdAndResult(cmd,"vulnerability","Vulnerability-"+testEntity.getTestClassName());
}
public String parseParameters(TestEntity testEntity) {
try {
switch (testEntity.getTestClassName().toLowerCase()) {
case "array_index_out_of_bounds_vulnerability"://have error
return cmd(testEntity, 0);
case "boundary_condition_vulnerability"://have error
return cmd(testEntity, 1);
case "buffer_overflow_vulnerability"://have error
return cmd(testEntity, 2);
case "command_injection_vulnerability"://have error
return cmd(testEntity, 3);
case "memory_duplicate_release_vulnerability"://have error
return cmd(testEntity, 4);
case "format_string_vulnerability"://have error
return cmd(testEntity, 5);
case "integer_overflow_vulnerability"://have error
return cmd(testEntity, 6);
case "numeric_error_vulnerability"://have error
return cmd(testEntity, 7);
case "symbol_extension_vulnerability"://have error
return cmd(testEntity, 8);
case "uaf_vulnerability"://have error
return cmd(testEntity, 9);
case "cross_script_vulnerability"://have error
return cmd(testEntity, 10);
case "sql_injection_vulnerability"://have error
return cmd(testEntity, 11);
default:
throw new FuzzException("Unknown method!");
}
} catch (FuzzException e) {
throw new FuzzException("Unknown class!");
}
}
private String cmd(TestEntity testEntity, int kindNum) {
return kitty.getVenvPath() + " " + kitty.getVulnerabilityTypePath() + "vul_types_test.py " + kindNum;
}
}
package com.example.fuzzControll.service.impl;
import com.example.fuzzControll.conf.IntegrationPathProperties;
import com.example.fuzzControll.service.websocketClientService;
import lombok.extern.slf4j.Slf4j;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.net.URI;
import java.net.URISyntaxException;
@Slf4j
@Service("websocketClientService")
public class websocketClientServiceImpl implements websocketClientService {
public static WebSocketClient webSocketClient = null;
@Autowired
IntegrationPathProperties properties;
@Override
public void connect() {
try {
webSocketClient = new WebSocketClient(new URI(properties.getWebSocketUri()+"fuzzIntegration")) {
@Override
public void onOpen(ServerHandshake serverHandshake) {
log.info("connect...");
}
@Override
public void onMessage(String s) {
log.info("get message:{}", s);
}
@Override
public void onClose(int i, String s, boolean b) {
log.info("disconnect code:{} reason:{} {}", i, s, b);
}
@Override
public void onError(Exception e) {
log.info("connect error!");
}
};
webSocketClient.connect();
}catch (URISyntaxException e){
e.printStackTrace();
}
}
@Override
public void disconnect() {
try {
webSocketClient.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
package com.example.fuzzControll.service;
import org.java_websocket.client.WebSocketClient;
public interface websocketClientService {
void connect();
void disconnect();
}
......@@ -35,56 +35,4 @@ public class FileTools {
}
}
/**
* 文件备份至数据库
*
* @param filename
* @return
*/
public byte[] fileReadAndTranstoBytes(String path, String filename) {
File file = new File(path + filename);
byte[] buffer = new byte[(int) file.length()];
try (
FileInputStream inputStream = new FileInputStream(file);
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);) {
System.out.println("1-2");
if (file.length() > Integer.MAX_VALUE && file.length() <= 0) {
log.error("KittyLogFile is too long or has no content!");
}
System.out.println("1-3");
int bytesRead;
while ((bytesRead = bufferedInputStream.read(buffer)) != -1) {
System.out.println(buffer.length);
}
System.out.println("1-5");
} catch (Exception e) {
e.printStackTrace();
}
return buffer;
}
/**
* 读取数据库文件至本地
*/
public void loadFileInLocal(String fileLoadPath, String fileName, byte[] fileBytes) {
File file = new File(fileLoadPath + "/" + fileName);
try (FileOutputStream fileOutputStream = new FileOutputStream(file);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(fileBytes);
BufferedInputStream bufferedInputStream = new BufferedInputStream(byteArrayInputStream);) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = bufferedInputStream.read(buffer)) != -1) {
bufferedOutputStream.write(buffer, 0, bytesRead);
}
} catch (FileNotFoundException e) {
throw new FileException("Cannot find path:" + fileLoadPath + "! Maybe there is no permission for this file!");
} catch (IOException e) {
throw new FileException("Load file failed!");
}
}
}
package com.example.fuzzControll.tools;
import com.example.fuzzControll.conf.AflnetProperties;
import com.example.fuzzControll.conf.KittyProperties;
import com.example.fuzzControll.conf.SpringContextUtil;
import com.example.fuzzControll.mapper.KittyMapper;
import com.example.fuzzControll.mapper.MissionInfoMapper;
import com.example.fuzzControll.service.AflnetPersistenceService;
import com.example.fuzzControll.service.KittyFuzzPersistenceService;
import java.util.concurrent.ConcurrentHashMap;
public class GlobalParameters {
public static ConcurrentHashMap<String, String> aflnetData = new ConcurrentHashMap<>();//当前aflnet任务的数据
public static KittyMapper kittyMapper = (KittyMapper) SpringContextUtil.getBean("KittyMapper");
public static KittyProperties kittyProperties = (KittyProperties) SpringContextUtil.getBean("kittyProperties");
public static KittyFuzzPersistenceService kittyFuzzPersistenceService =(KittyFuzzPersistenceService) SpringContextUtil.getBean("KittyFuzzPersistenceService");
public static AflnetProperties aflnetProperties = (AflnetProperties) SpringContextUtil.getBean("AflnetProperties");
public static AflnetPersistenceService aflnetPersistenceService = (AflnetPersistenceService) SpringContextUtil.getBean("AflnetPersistenceService");
public static MissionInfoMapper missionInfoMapper = (MissionInfoMapper) SpringContextUtil.getBean("MissionInfoMapper");
}
package com.example.fuzzControll.tools;
//todo 对ip等增加正则判断
public class RegularTools {
}
package com.example.fuzzControll.tools;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class TestTools {
public static boolean paramsLenghtTest(int paramsLen, int needParamsLen, String name) {
Boolean isOk = paramsLen == needParamsLen;
return isOk == true ? true : false;
}
}
mybatis:
# 配置mapper的扫描,找到所有的mapper.xml映射文件
mapperLocations: classpath*:mapper/**/*Mapper.xml
# 加载全局的配置文件
configLocation: classpath:mybatis/mybatis-config.xml
logging:
pattern:
file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"
......@@ -24,35 +18,4 @@ aflnet:
outputPath: "/home/" #D:/code/companyProjects/files/
aflnetPath: "/usr/fuzzenv/fuzzenv/"#alfnet路径
kitty:
logOutPath: "/home/kittylogs/"#kitty协议模板日志生成路径
path: "/usr/fuzzenv/fuzzenv/fuzz50/kitty/renix/" #kitty项目下的各协议生成模板python文件路径
venvPath: "/usr/fuzzenv/fuzzenv/fuzz50/kitty/venv/bin/python"
methodPath: "/usr/fuzzenv/fuzzenv/fuzz50/kitty/2020test/"#kitty下变异方法路径
vulnerabilityTypePath: "/usr/fuzzenv/fuzzenv/fuzz50/kitty/2020test/"#kitty下漏洞类型python路径
mutationPath: "/usr/fuzzenv/fuzzenv/fuzz50/kitty/2020test/"
templateInfoHttp: "http://127.0.0.1:26001/api/template_info.json"#模板信息请求链接
statsHttp: "http://127.0.0.1:26001"#运行时数据
stagesHttp: "http://127.0.0.1:26001/api/stages.json"#
reportHttp: "http://127.0.0.1:26001/api/report"#
spring:
cloud:
nacos:
discovery:
server-addr: http://${nacos-docker.ip}:8848
datasource:
url: jdbc:mysql://${mysql-docker.ip}:3306/fuzz?allowPublicKeyRetrieval=true&useSSL=falseuseUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
integrationpath:
webSocketUri: ws://${fuzzmaster-docker.ip}:8101/websocket/testResult/
nacos-docker:
ip: 192.168.50.247
fuzzmaster-docker:
ip: 192.168.50.247
mysql-docker:
ip: 192.168.50.247
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.fuzzControll.mapper.AflnetMapper">
<resultMap type="com.example.fuzzControll.pojo.vo.AflnetResult" id="AflnetResult">
<result property="id" column="id" />
<result property="missionId" column="missionId" />
<result property="file" column="file" />
<result property="fileName" column="fileName" />
</resultMap>
<sql id="selectAlfnetResult">
select id, missionId,file, fileName from alfnetResult
</sql>
<insert id="aflnetOutputBackup">
insert into alfnetResult(id,missionId, file, fileName) values(#{id}, #{missionId},#{file}, #{fileName})
</insert>
<select id="selectResultById" resultMap="AflnetResult">
<include refid="selectAlfnetResult"/>
where missionId = #{missionId};
</select>
</mapper>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.fuzzControll.mapper.KittyMapper">
<resultMap type="com.example.fuzzControll.pojo.vo.KittyResult" id="KittyResult">
<result property="id" column="id" />
<result property="missionId" column="missionId" />
<result property="resultOut" column="resultOut" />
<result property="resultError" column="resultError" />
</resultMap>
<resultMap type="com.example.fuzzControll.pojo.vo.KittyPackageFile" id="kittyPackageFile">
<result property="id" column="id" />
<result property="missionId" column="missionId" />
<result property="kittyRecvFile" column="kittyRecvFile" />
<result property="kittySendFile" column="kittySendFile" />
<result property="kittyRecvFileName" column="kittyRecvFileName" />
<result property="kittySendFileName" column="kittySendFileName" />
</resultMap>
<sql id="selectKittyResult">
select id, missionId,resultOut, resultError from kittyResult
</sql>
<sql id="selectKittyPackageFile">
select id,missionId, kittyRecvFile, kittySendFile,kittyRecvFileName,kittySendFileName from kittyPackageFile;
</sql>
<insert id="kittyResultsBackup">
insert into kittyResult(id,missionId, resultOut, resultError) values(#{id}, #{missionId},#{resultOut}, #{resultError})
</insert>
<insert id="kittyPackagesBackup">
insert into kittyPackageFile(id,missionId, kittyRecvFile, kittySendFile,kittyRecvFileName,kittySendFileName) values(#{id}, #{missionId},#{kittyRecvFile}, #{kittySendFile}, #{kittyRecvFileName}, #{kittySendFileName})
</insert>
<select id="getKittyResults" resultMap="KittyResult">
<include refid="selectKittyResult"/>
</select>
<select id="getKittyPackageFileById" resultType="com.example.fuzzControll.pojo.vo.KittyPackageFile">
<include refid="selectKittyPackageFile"/>
where missionId=#{missionId}
</select>
<select id="getKittyResultByMissionId" resultType="com.example.fuzzControll.pojo.vo.KittyResult">
<include refid="selectKittyResult"/>
where missionId = #{missionId}
</select>
</mapper>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.fuzzControll.mapper.MissionInfoMapper">
<resultMap type="com.example.fuzzControll.pojo.vo.MissionInfo" id="MissionInfo">
<result property="id" column="id" />
<result property="missionId" column="missionId" />
<result property="tableId" column="tableId" />
<result property="createTime" column="createTime" />
<result property="missionName" column="missionName" />
</resultMap>
<sql id="selectMissionInfo">
select id, missionId,tableId, createTime,missionName from missionIdInfo
</sql>
<insert id="insertMission">
insert into missionIdInfo(missionId,tableId, createTime,missionName) values(#{missionId}, #{tableId},#{createTime}, #{missionName})
</insert>
<select id="selectByMissionId" resultMap="MissionInfo">
<include refid="selectMissionInfo"/>
where missionId = #{missionId}
</select>
<select id="selectMissionInfoList" resultType="com.example.fuzzControll.pojo.vo.MissionInfo">
<include refid="selectMissionInfo"/>
</select>
<select id="selectTopMissionId" resultType="java.lang.Integer">
select IFNULL((select missionId from missionIdInfo order by missionId desc limit 1),0) as missionId;
</select>
</mapper>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 全局参数 -->
<settings>
<!-- 使全局的映射器启用或禁用缓存 -->
<setting name="cacheEnabled" value="true" />
<!-- 允许JDBC 支持自动生成主键 -->
<setting name="useGeneratedKeys" value="true" />
<!-- 配置默认的执行器.SIMPLE就是普通执行器;REUSE执行器会重用预处理语句(prepared statements);BATCH执行器将重用语句并执行批量更新 -->
<setting name="defaultExecutorType" value="SIMPLE" />
<!-- 指定 MyBatis 所用日志的具体实现 -->
<setting name="logImpl" value="SLF4J" />
<!-- 使用驼峰命名法转换字段 -->
<!-- <setting name="mapUnderscoreToCamelCase" value="true"/> -->
</settings>
</configuration>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment