/*
* Copyright, Aspect Security, Inc.
*
* This file is part of JavaSnoop.
*
* JavaSnoop is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JavaSnoop is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with JavaSnoop. If not, see <http://www.gnu.org/licenses/>.
*/
package com.aspect.snoop.ui.tamper.bytearray;
import com.aspect.snoop.JavaSnoop;
import com.aspect.snoop.ui.tamper.common.EditStringView;
import com.aspect.snoop.util.IOUtil;
import com.aspect.snoop.util.UIUtil;
import java.awt.event.ActionEvent;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import org.jdesktop.application.Action;
public class EditByteArrayView extends javax.swing.JDialog {
private byte[] bytes;
public byte[] getBytes() {
return bytes;
}
HexTableCellEditor editor;
public EditByteArrayView(java.awt.Frame parent, boolean modal, byte[] bytes) {
super(parent, modal);
initComponents();
this.bytes = bytes;
lblByteCount.setText(""+bytes.length);
tblOriginalBytes.setCellSelectionEnabled(true);
tblOriginalBytes.setModel( new ByteArrayTableModel(tblAsciiBytes, bytes) );
tblOriginalBytes.setDefaultRenderer(Byte.class, new CenteredCellRenderer(tblAsciiBytes));
tblOriginalBytes.setDragEnabled(false);
TableSelectionHandler originalHandler = new TableSelectionHandler(tblOriginalBytes, tblAsciiBytes);
tblOriginalBytes.getColumnModel().addColumnModelListener(originalHandler);
tblOriginalBytes.getSelectionModel().addListSelectionListener(originalHandler);
editor = new HexTableCellEditor();
tblOriginalBytes.setDefaultEditor(Byte.class, editor);
tblAsciiBytes.setDragEnabled(false);
tblAsciiBytes.setCellSelectionEnabled(true);
tblAsciiBytes.setModel ( new AsciiArrayTableModel(tblOriginalBytes, bytes) );
tblAsciiBytes.setDefaultRenderer(Character.class, new CenteredCellRenderer(tblOriginalBytes));
TableSelectionHandler asciiHandler = new TableSelectionHandler(tblAsciiBytes, tblOriginalBytes);
tblAsciiBytes.getColumnModel().addColumnModelListener(asciiHandler);
tblAsciiBytes.getSelectionModel().addListSelectionListener(asciiHandler);
for(int i=0;i<16;i++) {
tblOriginalBytes.getColumnModel().getColumn(i).setResizable(false);
tblAsciiBytes.getColumnModel().getColumn(i).setResizable(false);
}
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
btnViewGroup = new javax.swing.ButtonGroup();
originalPane = new javax.swing.JScrollPane();
tblOriginalBytes = new javax.swing.JTable();
jLabel1 = new javax.swing.JLabel();
lblByteCount = new javax.swing.JLabel();
btnReplaceWithString = new javax.swing.JButton();
btnChangeByteArraySize = new javax.swing.JButton();
jLabel3 = new javax.swing.JLabel();
btnReplaceWithInt = new javax.swing.JButton();
btnReplaceWithShort = new javax.swing.JButton();
btnReplaceWithLong = new javax.swing.JButton();
btnReplaceWithFloat = new javax.swing.JButton();
btnReplaceWithDouble = new javax.swing.JButton();
btnReplaceWithFile = new javax.swing.JButton();
btnEditAsString = new javax.swing.JButton();
asciiPane = new javax.swing.JScrollPane();
tblAsciiBytes = new javax.swing.JTable();
btnAcceptChanges = new javax.swing.JButton();
rdoHex = new javax.swing.JRadioButton();
rdoAscii = new javax.swing.JRadioButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(com.aspect.snoop.JavaSnoop.class).getContext().getResourceMap(EditByteArrayView.class);
setTitle(resourceMap.getString("Form.title")); // NOI18N
setName("Form"); // NOI18N
setResizable(false);
originalPane.setName("originalPane"); // NOI18N
tblOriginalBytes.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{null, null, null, null},
{null, null, null, null},
{null, null, null, null},
{null, null, null, null}
},
new String [] {
"Title 1", "Title 2", "Title 3", "Title 4"
}
));
tblOriginalBytes.setName("tblOriginalBytes"); // NOI18N
originalPane.setViewportView(tblOriginalBytes);
jLabel1.setText(resourceMap.getString("jLabel1.text")); // NOI18N
jLabel1.setName("jLabel1"); // NOI18N
lblByteCount.setText(resourceMap.getString("lblByteCount.text")); // NOI18N
lblByteCount.setName("lblByteCount"); // NOI18N
javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(com.aspect.snoop.JavaSnoop.class).getContext().getActionMap(EditByteArrayView.class, this);
btnReplaceWithString.setAction(actionMap.get("replaceBytesAsString")); // NOI18N
btnReplaceWithString.setText(resourceMap.getString("btnReplaceWithString.text")); // NOI18N
btnReplaceWithString.setFocusable(false);
btnReplaceWithString.setName("btnReplaceWithString"); // NOI18N
btnChangeByteArraySize.setAction(actionMap.get("changeArrayByteSize")); // NOI18N
btnChangeByteArraySize.setText(resourceMap.getString("btnChangeByteArraySize.text")); // NOI18N
btnChangeByteArraySize.setFocusable(false);
btnChangeByteArraySize.setName("btnChangeByteArraySize"); // NOI18N
jLabel3.setText(resourceMap.getString("jLabel3.text")); // NOI18N
jLabel3.setName("jLabel3"); // NOI18N
btnReplaceWithInt.setAction(actionMap.get("replaceBytesAsNumber")); // NOI18N
btnReplaceWithInt.setText(resourceMap.getString("btnReplaceWithInt.text")); // NOI18N
btnReplaceWithInt.setFocusable(false);
btnReplaceWithInt.setName("btnReplaceWithInt"); // NOI18N
btnReplaceWithShort.setAction(actionMap.get("replaceBytesAsNumber")); // NOI18N
btnReplaceWithShort.setText(resourceMap.getString("btnReplaceWithShort.text")); // NOI18N
btnReplaceWithShort.setFocusable(false);
btnReplaceWithShort.setName("btnReplaceWithShort"); // NOI18N
btnReplaceWithLong.setAction(actionMap.get("replaceBytesAsNumber")); // NOI18N
btnReplaceWithLong.setText(resourceMap.getString("btnReplaceWithLong.text")); // NOI18N
btnReplaceWithLong.setFocusable(false);
btnReplaceWithLong.setName("btnReplaceWithLong"); // NOI18N
btnReplaceWithFloat.setAction(actionMap.get("replaceBytesAsNumber")); // NOI18N
btnReplaceWithFloat.setText(resourceMap.getString("btnReplaceWithFloat.text")); // NOI18N
btnReplaceWithFloat.setFocusable(false);
btnReplaceWithFloat.setName("btnReplaceWithFloat"); // NOI18N
btnReplaceWithDouble.setAction(actionMap.get("replaceBytesAsNumber")); // NOI18N
btnReplaceWithDouble.setText(resourceMap.getString("btnReplaceWithDouble.text")); // NOI18N
btnReplaceWithDouble.setFocusable(false);
btnReplaceWithDouble.setName("btnReplaceWithDouble"); // NOI18N
btnReplaceWithFile.setAction(actionMap.get("replaceBytesFromFile")); // NOI18N
btnReplaceWithFile.setText(resourceMap.getString("btnReplaceWithFile.text")); // NOI18N
btnReplaceWithFile.setFocusable(false);
btnReplaceWithFile.setName("btnReplaceWithFile"); // NOI18N
btnEditAsString.setAction(actionMap.get("editBytesAsString")); // NOI18N
btnEditAsString.setText(resourceMap.getString("btnEditAsString.text")); // NOI18N
btnEditAsString.setFocusable(false);
btnEditAsString.setName("btnEditAsString"); // NOI18N
asciiPane.setName("asciiPane"); // NOI18N
tblAsciiBytes.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{null, null, null, null},
{null, null, null, null},
{null, null, null, null},
{null, null, null, null}
},
new String [] {
"Title 1", "Title 2", "Title 3", "Title 4"
}
));
tblAsciiBytes.setName("tblAsciiBytes"); // NOI18N
asciiPane.setViewportView(tblAsciiBytes);
btnAcceptChanges.setText(resourceMap.getString("btnAcceptChanges.text")); // NOI18N
btnAcceptChanges.setName("btnAcceptChanges"); // NOI18N
btnAcceptChanges.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnAcceptChangesActionPerformed(evt);
}
});
rdoHex.setAction(actionMap.get("changeView")); // NOI18N
btnViewGroup.add(rdoHex);
rdoHex.setSelected(true);
rdoHex.setText(resourceMap.getString("rdoHex.text")); // NOI18N
rdoHex.setName("rdoHex"); // NOI18N
rdoAscii.setAction(actionMap.get("changeView")); // NOI18N
btnViewGroup.add(rdoAscii);
rdoAscii.setText(resourceMap.getString("rdoAscii.text")); // NOI18N
rdoAscii.setName("rdoAscii"); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addComponent(btnEditAsString, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(lblByteCount, javax.swing.GroupLayout.PREFERRED_SIZE, 65, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(btnChangeByteArraySize, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(10, 10, 10)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(btnReplaceWithString, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnReplaceWithShort))
.addComponent(jLabel3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 136, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnReplaceWithInt)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnReplaceWithLong)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnReplaceWithFloat)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnReplaceWithDouble)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnReplaceWithFile))
.addGroup(layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(rdoHex)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(rdoAscii))))
.addGroup(layout.createSequentialGroup()
.addComponent(originalPane, javax.swing.GroupLayout.PREFERRED_SIZE, 428, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(asciiPane, javax.swing.GroupLayout.PREFERRED_SIZE, 430, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap(767, Short.MAX_VALUE)
.addComponent(btnAcceptChanges)
.addContainerGap())
);
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {asciiPane, originalPane});
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel1)
.addComponent(lblByteCount))
.addGap(35, 35, 35))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(jLabel3)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnReplaceWithString)
.addComponent(btnReplaceWithInt)
.addComponent(btnReplaceWithLong)
.addComponent(btnChangeByteArraySize)
.addComponent(btnReplaceWithShort)
.addComponent(btnReplaceWithFloat)
.addComponent(btnReplaceWithDouble)
.addComponent(btnReplaceWithFile))))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnEditAsString)
.addComponent(rdoHex)
.addComponent(rdoAscii))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(asciiPane, 0, 0, Short.MAX_VALUE)
.addComponent(originalPane, javax.swing.GroupLayout.DEFAULT_SIZE, 210, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnAcceptChanges)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void btnAcceptChangesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAcceptChangesActionPerformed
dispose();
}//GEN-LAST:event_btnAcceptChangesActionPerformed
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
EditByteArrayView dialog = new EditByteArrayView(new javax.swing.JFrame(), true, "foobar".getBytes());
dialog.addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent e) {
System.exit(0);
}
});
dialog.setVisible(true);
}
});
}
@Action
public void changeArrayByteSize() {
String num = JOptionPane.showInputDialog("Enter new array size: ");
if ( num != null ) {
int oldSize = bytes.length;
int newSize = Integer.parseInt(num);
byte[] newArray = new byte[newSize];
if ( newSize >= oldSize ) {
for(int i=0;i<oldSize;i++) {
newArray[i] = bytes[i];
}
for(int i=oldSize;i<newSize;i++) {
newArray[i] = 0;
}
} else {
for(int i=0;i<newSize;i++) {
newArray[i] = bytes[i];
}
}
bytes = newArray;
updateTable();
}
}
@Action
public void editBytesAsString() {
EditStringView view = new EditStringView(this, true, "");
view.setVisible(true);
UIUtil.waitForInput(view);
bytes = view.getText().getBytes();
updateTable();
}
@Action
public void replaceBytesAsString() {
String s = new String(bytes);
EditStringView view = new EditStringView(this, true, s);
view.setVisible(true);
UIUtil.waitForInput(view);
bytes = view.getText().getBytes();
updateTable();
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JScrollPane asciiPane;
private javax.swing.JButton btnAcceptChanges;
private javax.swing.JButton btnChangeByteArraySize;
private javax.swing.JButton btnEditAsString;
private javax.swing.JButton btnReplaceWithDouble;
private javax.swing.JButton btnReplaceWithFile;
private javax.swing.JButton btnReplaceWithFloat;
private javax.swing.JButton btnReplaceWithInt;
private javax.swing.JButton btnReplaceWithLong;
private javax.swing.JButton btnReplaceWithShort;
private javax.swing.JButton btnReplaceWithString;
private javax.swing.ButtonGroup btnViewGroup;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel lblByteCount;
private javax.swing.JScrollPane originalPane;
private javax.swing.JRadioButton rdoAscii;
private javax.swing.JRadioButton rdoHex;
private javax.swing.JTable tblAsciiBytes;
private javax.swing.JTable tblOriginalBytes;
// End of variables declaration//GEN-END:variables
@Action
public void replaceBytesAsNumber(ActionEvent evt) {
String num = JOptionPane.showInputDialog("Enter new value: ");
if ( num == null )
return;
if ( evt.getActionCommand().equals("short") ) {
Short s = Short.parseShort(num);
bytes = shortToByteArray(s);
} else if ( evt.getActionCommand().equals("int") ) {
Integer s = Integer.parseInt(num);
bytes = intToByteArray(s);
} else if ( evt.getActionCommand().equals("long") ) {
Long s = Long.parseLong(num);
bytes = longToByteArray(s);
} else if ( evt.getActionCommand().equals("double") ) {
Double s = Double.parseDouble(num);
bytes = doubleToByteArray(s);
} else if ( evt.getActionCommand().equals("float") ) {
Float s = Float.parseFloat(num);
bytes = floatToByteArray(s);
}
updateTable();
}
public static byte[] shortToByteArray(short value) {
return new byte[] {
(byte)(value >>> 8),
(byte)value};
}
public static byte[] intToByteArray(int value) {
return new byte[] {
(byte)(value >>> 24),
(byte)(value >>> 16),
(byte)(value >>> 8),
(byte)value};
}
public static byte[] longToByteArray(long value) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
try {
dos.writeLong(value);
} catch (IOException ex) {
// if this fails we have much bigger issues than lost integrity here
}
return baos.toByteArray();
}
public static byte[] floatToByteArray(float value) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
try {
dos.writeFloat(value);
} catch (IOException ex) {
// if this fails we have much bigger issues than lost integrity here
}
return baos.toByteArray();
}
public static byte[] doubleToByteArray(double value) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
try {
dos.writeDouble(value);
} catch (IOException ex) {
// if this fails we have much bigger issues than lost integrity here
}
return baos.toByteArray();
}
static File lastFile = null;
@Action
public void replaceBytesFromFile() {
JFileChooser fc;
if ( lastFile != null ) {
fc = new JFileChooser(lastFile.getParentFile());
} else {
fc = new JFileChooser();
}
int rc = fc.showOpenDialog(this);
if (rc == JFileChooser.APPROVE_OPTION) {
lastFile = fc.getSelectedFile();
try {
bytes = IOUtil.getBytesFromFile(lastFile);
updateTable();
} catch (IOException ex) {
UIUtil.showErrorMessage(this, "Error reading file: " + ex.getMessage());
}
}
}
private void updateTable() {
AsciiArrayTableModel modelA = (AsciiArrayTableModel)tblAsciiBytes.getModel();
ByteArrayTableModel modelB = (ByteArrayTableModel)tblOriginalBytes.getModel();
modelA.setBytes(bytes);
modelB.setBytes(bytes);
tblAsciiBytes.updateUI();
tblOriginalBytes.updateUI();
tblAsciiBytes.repaint();
tblOriginalBytes.repaint();
}
@Action
public void changeView(ActionEvent evt) {
ByteArrayTableModel model = (ByteArrayTableModel)tblOriginalBytes.getModel();
if ( evt.getActionCommand().startsWith("Hex")) {
model.showInHex(true);
editor.shouldEditInHex(true);
} else {
model.showInHex(false);
editor.shouldEditInHex(false);
}
tblOriginalBytes.repaint();
}
}