/* * 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(); } }