给Cknife加个Xor加密

目的

分析一下Cknife的源码,学习Java,顺便修改Cknife,为其添加异或的加密方式,看看能不能绕过一些waf。

src/com/ms509/ui/Cknife.java

入口点

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Cknife {
public static void main(String[] args) {
// TODO Auto-generated method stub
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new InitConfig(); //配置初始化
setLookFeel(); //外观
new MainFrame(); //主窗口

}
});
}

EventQueueimport java.awt.EventQueue;这个导入进来的。

InitConfig

三个方法:

  • Init()
  • WriteParams()
  • LoadParams()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private void Init() {
File conf = new File("Config.ini");
if (conf.exists()) {
// WriteParams(); //调试的时候取消注释,即无论怎么都要重新写一遍配置文件,发布的时候不要忘记注释掉。
LoadParams();
} else {
WriteParams();
LoadParams();

}
}

private void WriteParams() {
Configuration config = new Configuration();
config.setValue("SPL", "->|");
config.setValue("SPR", "|<-");
config.setValue("CODE", "code");
config.setValue("ACTION", "action");
config.setValue("PARAM1", "z1");
....
}

private void LoadParams() {
Configuration config = new Configuration();
Safe.SPL = config.getValue("SPL");
Safe.SPR = config.getValue("SPR");
Safe.CODE = config.getValue("CODE");
....
}

检测配置文件是否存在,如果存在,加载配置项;如果不存在,写默认配置文件到磁盘,然后加载配置。

setLookFeel()

这个是加载外观的,不看了,与主要逻辑没啥关系。

MainFrame()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public MainFrame() {
// TODO Auto-generated constructor stub
Toolkit t = Toolkit.getDefaultToolkit();
Dimension d = t.getScreenSize();
main = new JFrame("Cknife 1.0 Release");
main.setIconImage(new ImageIcon(getClass().getResource("/com/ms509/images/main.png")).getImage());
main.setSize(900, 480);
main.setLocation((d.width - main.getWidth()) / 2,
(d.height - main.getHeight()) / 2);
main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main.getContentPane().setLayout(new BorderLayout(0, 0));
tab = new TabFrame(); //这个才是操作界面的窗口
tab.addPanel("list"); //这是addPanel的参数,后面会用到
main.add(tab);
main.setVisible(true);
}
1
2
3
4
5
6
7
8
9
package com.ms509.ui;

import javax.swing.*;
import java.awt.*;

public class MainFrame {
public static TabFrame tab;
...
}

TabFrame是包中的,跟进去看下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class TabFrame extends JTabbedPane {
private ListPanel list;
private String url;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public JPanel addPanel(String type) { // 从MainFrame调用到这里,并传递了list参数
switch (type) {
case "list":
if(list==null)
{
list = new ListPanel(); // 这里新建了一个ListPanel对象,跟进去看一眼
this.addTab("列表", list); //将上面的ListPanel以“列表”为名称添加到TabFrame
this.setSelectedIndex(this.indexOfComponent(list));
}
return list;
case "database":
DatabasePanel database = new DatabasePanel();
this.addTab("数据库管理", database);
this.setSelectedIndex(this.indexOfComponent(database));
this.setTabComponentAt(this.getTabCount()-1, new HeadPanel(database));
return database;
case "filemanager":
FileManagerPanel filemanager = new FileManagerPanel();
this.addTab("文件管理", filemanager);
this.setSelectedIndex(this.indexOfComponent(filemanager));
this.setTabComponentAt(this.getTabCount()-1, new HeadPanel(filemanager));
return filemanager;
case "shell":
ShellPanel shell = new ShellPanel();
this.addTab("模拟终端", shell);
this.setSelectedIndex(this.indexOfComponent(shell));
this.setTabComponentAt(this.getTabCount()-1, new HeadPanel(shell));
shell.setVisible(true);
shell.requestFocus();
return shell;
case "text":
TextPanel text = new TextPanel();
this.addTab("文本文件", text);
this.setSelectedIndex(this.indexOfComponent(text));
this.setTabComponentAt(this.getTabCount()-1, new HeadPanel(text));
return text;
default:
return null;
}

}

}

ListPanel()构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public ListPanel() {
// TODO Auto-generated constructor stub
this.setLayout(new GridBagLayout());
GBC gbclist = new GBC(0, 0).setFill(GBC.BOTH).setWeight(100, 100);
GBC gbcbar = new GBC(0, 1).setFill(GBC.HORIZONTAL).setWeight(100, 0);
JTable list = new JTable();

list.setAutoCreateRowSorter(true);
ResultSet rs = null;
try { //从数据库中获取所有的shell信息 ==> rs
rs = DbDao.getInstance().getStmt()
.executeQuery("select * from data");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
model = new ResultSetTableModel(rs);
list.setModel(model);

TableColumnModel cmodel = list.getColumnModel();
TableColumn tableurl = cmodel.getColumn(1);
tableurl.setMinWidth(500);
int[] arr = { 0, 2, 3, 4, 5 };
for (int i : arr) {
TableColumn column = cmodel.getColumn(i);
column.setMinWidth(0);
column.setMaxWidth(0);
}
JToolBar bar = new JToolBar();
bar.setFloatable(false);
status = new JLabel("完成");
JScrollPane listPane = new JScrollPane(list);
new ListPopMenu(this, listPane); //右键菜单,列表项的
new ListPopMenu(this, list); //右键菜单,列表窗口的
// listPane.setComponentPopupMenu(new ListPopMenu(this, listPane));
// //swing弹出菜单,不需要awt监听事件。
// list.setComponentPopupMenu(new ListPopMenu(this, list));
this.add(listPane, gbclist);
bar.add(status);
this.add(bar, gbcbar);
}

到这,我们就看到了主界面,来看下右键菜单部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
public class ListPopMenu extends JPopupMenu {
private JScrollPane listPane;
private JMenuItem add, edit, delete, database, filemanager, shell, about,config;
private JTable list;
private JPopupMenu pop;

public ListPopMenu(JPanel panel, JScrollPane listPane) {//如果传进来的是JScrollPane对象的话,就走这个构造函数,也就是我们在空白地方点右键的时候,会生成下面的右键菜单
/*
* 要添加异或加密的话,我们需要在“添加”对话框中加入一个用来指定异或密钥的地方
*/
// TODO Auto-generated constructor stub
this.listPane = listPane;
pop = this;
this.listPane.addMouseListener(new MouseAction());
MenuAction action = new MenuAction(); //这个是对菜单项的动作的对象,跟进去
add = new JMenuItem("添加"); //这里会新建一个JMenuItem对象,用来生成菜单项
JMenu skins = new JMenu("皮肤");
about = new JMenuItem("关于");
config = new JMenuItem("设置");
LookAndFeelInfo[] looks = UIManager.getInstalledLookAndFeels();
ButtonGroup group = new ButtonGroup();
JCheckBoxMenuItem gskin = new JCheckBoxMenuItem("Graphite");
SkinAction action1 = new SkinAction();
action1.setLookAndFeel("org.pushingpixels.substance.api.skin.SubstanceGraphiteLookAndFeel");
gskin.addActionListener(action1);
group.add(gskin);
skins.add(gskin);
for(LookAndFeelInfo look : looks)
{
JCheckBoxMenuItem skin = new JCheckBoxMenuItem(look.getName());
SkinAction action2 = new SkinAction();
action2.setLookAndFeel(look.getClassName());
skin.addActionListener(action2);
group.add(skin);
skins.add(skin);
}
add.addActionListener(action);
about.addActionListener(action);
config.addActionListener(action);
pop.add(add);
pop.add(skins);
pop.add(about);
this.addSeparator();
pop.add(config);
panel.add(this);
}

public ListPopMenu(JPanel panel, JTable list) {//如果传进来的是JTable对象的话,就走这个构造函数

this.list = list;
pop = this;
this.list.addMouseListener(new SelectedMouseAction());
MenuAction action = new MenuAction();
filemanager = new JMenuItem("文件管理");
database = new JMenuItem("数据库管理");
shell = new JMenuItem("模拟终端");
database.addActionListener(action);
filemanager.addActionListener(action);
shell.addActionListener(action);
this.add(filemanager);
this.add(database);
this.add(shell);
this.addSeparator();
add = new JMenuItem("添加");
edit = new JMenuItem("编辑");
delete = new JMenuItem("删除");
config = new JMenuItem("设置");
this.add(add);
this.add(edit);
this.add(delete);
this.addSeparator();
this.add(config);
add.addActionListener(action);
edit.addActionListener(action);
delete.addActionListener(action);
config.addActionListener(action);
database.setEnabled(true);
panel.add(this);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
class MenuAction implements ActionListener { //继承ActionListener
/*
MenuAction一共有如下几个事件:
- add, 增加shell
- edit, 修改编辑shell
- delete, 删除shell
- filemanager, 文件管理
- database, 数据库管理
- shell, 命令行
- about, 关于
- config, 配置
*/

@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if (e.getSource() == add) { //如果是add事件,则新建AddDialog对话框对象,快到关键类了,跟进
AddDialog add = new AddDialog();
} else if (e.getSource() == edit) { //如果是修改,则
AddDialog edit = new AddDialog(getOne(list));
} else if (e.getSource() == delete) { //如果是删除,则
int button = JOptionPane.showConfirmDialog(MainFrame.main,
"确认删除?", "提示", JOptionPane.YES_NO_OPTION);
if (button == 0) {
Statement stmt = DbDao.getInstance().getStmt();
try {
String id = getOne(list).split("\t")[0];
stmt.executeUpdate("delete from data where id=" + id);
ListPanel listpanel= (ListPanel)MainFrame.tab.getSelectedComponent();
listpanel.getModel().remove(id);
listpanel.getStatus().setText("删除成功");
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
} else if (e.getSource() == filemanager) { //如果是文件管理,则
MainFrame.tab.setUrl(getOne(list));
Runnable run = new Runnable() {
public void run() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MainFrame.tab.addPanel("filemanager");
}
});

}
};
new Thread(run).start();
} else if (e.getSource() == database) { //如果是数据库管理,则
MainFrame.tab.setUrl(getOne(list));
MainFrame.tab.addPanel("database");
} else if (e.getSource() == shell) { //如果是命令行,则
MainFrame.tab.setUrl(getOne(list));
Runnable run = new Runnable() {
public void run() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MainFrame.tab.addPanel("shell");
}
});

}
};
new Thread(run).start();
} else if (e.getSource() == about) { //如果是关于,则
AboutDialog a = new AboutDialog();
} else if (e.getSource() == config) //如果是配置,则
{
new ConfigDialog();
}
}

AddDialog()就是我们要找的关键类了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
public class AddDialog extends JDialog {
private String id,ip,time;
private JButton button;
private JTextField urltext, passtext, xortext;
private JTextArea configtext;
private JComboBox<String> atype, acode;

public AddDialog() {
super(MainFrame.main, "添加SHELL", true);
this.setComponent();
this.setEvent();
this.setVisible(true); // 模态对话框必须在添加完组件后设置可见,不然会显示不了。
}

public AddDialog(String s) {
super(MainFrame.main, "修改SHELL", true);
String[] tmp = s.split("\t");
this.setComponent();
this.setEvent();
this.id = tmp[0];
urltext.setText(tmp[1]);
passtext.setText(tmp[2]);
configtext.setText(tmp[3]);
button.setText("编辑");
atype.setSelectedItem(tmp[4]);
acode.setSelectedItem(tmp[5]);
this.ip = tmp[6];
this.time = tmp[7];
this.setVisible(true); // 模态对话框必须在添加完组件后设置可见,不然会显示不了。
}

private void setComponent() {
/*
这里就是我们要找的了。
*/
Toolkit t = Toolkit.getDefaultToolkit();
Dimension d = t.getScreenSize();
this.setResizable(false);
this.setSize(450, 240);
this.setLocation((d.width - this.getWidth()) / 2,
(d.height - this.getHeight()) / 2);
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
JPanel north = new JPanel();//三个Jpanel对就于添加对话框的上、中、下有一个部分。
JPanel center = new JPanel();
JPanel south = new JPanel();
north.setLayout(new FlowLayout(FlowLayout.LEFT, 3, 8)); //设置每个部分的layout类型
center.setLayout(new FlowLayout(FlowLayout.LEFT, 3, 0));
south.setLayout(new FlowLayout(FlowLayout.RIGHT, 3, 8));
JLabel urllabel = new JLabel("地址:");
urllabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
JLabel configlabel = new JLabel("配置:");
configlabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
JLabel actionlabel = new JLabel("");
actionlabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
urltext = new JTextField("http://"); //Shell的地址
passtext = new JTextField(); //连接密码
configtext = new JTextArea(); //配置内容
JScrollPane configscroll = new JScrollPane(configtext);
button = new JButton("添加");
String[] strtype = new String[] { "脚本类型", "ASP(Eval)", "ASPX(Eval)", "PHP(Eval)",
"JSP(Eval)", "Customize" };
String[] strcode = new String[] { "字符编码", "GB2312", "GBK", "UTF-8",
"BIG5", "ISO-8859-1" };
atype = new JComboBox<>(strtype);
acode = new JComboBox<>(strcode);
urltext.setPreferredSize(new Dimension(320,23)); //Shell地址输入框的大小
passtext.setPreferredSize(new Dimension(56,23)); //连接密码输入框的大小
configtext.setLineWrap(true); //配置框中内容自动换行
configtext.setPreferredSize(new Dimension(369,128));
configscroll.setBorder(urltext.getBorder());
/*
下面是将各种控件添加到布局中,所以在这之前,我们要新建一个自己的控件,异或的话,用xor+输入框。逻辑部分后面再跟,先完成界面。
*/
JLabel xorlabel = new JLabel("XOR:");
xorlabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
xortext = new JTextField(); //XOR密钥
xortextsetPreferredSize(new Dimension(56,23)); //设置大小
north.add(urllabel);
north.add(urltext);
north.add(passtext);
center.add(configlabel);
center.add(configscroll);
/*
* xor-related
*/
south.add(xorlabel);
south.add(xortext);

south.add(atype);
south.add(acode);
south.add(button);
south.add(actionlabel);
this.getContentPane().add(north, BorderLayout.NORTH);
this.getContentPane().add(center, BorderLayout.CENTER);
this.getContentPane().add(south, BorderLayout.SOUTH);
this.getRootPane().setDefaultButton(button);
}

....
}

别处先不管,来运行一下,看看效果:
upload successful

恩,说明咱们找对了。还有逻辑层的东西需要修改,不然只有功能没有实现。

我也不知道会分为几篇才能写完这个,最近时候比较紧,尽快吧。