I have a pcap file and I can view the hex and human-readable string equivalent of the hexdump using wireshark. However, I want to do the same but in Java. Here is a screenshot from Wireshark application.
Taking the highlighted string, this is what i've come but the output is not what I've expect. Can someone help me? Thank you very much
String hex = "a106020110020138";
byte[] bts = new byte[hex.length() / 2];
for (int i = 0; i < bts.length; i++) {
bts[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
}
String c = new String(bts, StandardCharsets.US_ASCII);
System.out.println(c);
This is the output:
Java uses UTF-16 for characters, in what byte order i forgot, meaning you need to use two bytes per character.
If you want the output to look exactly like Wireshark's, you can do by reading each group of two hex digits, and keeping that ones that correspond to printable ASCII characters:
public class Pcap {
public static void main(String[] args) {
String hex = "701c2f676c08a106020110020138";
int n = hex.length();
char[] cs = new char[n / 2];
for (int i = 0; i < n; i+=2)
cs[i/2] = (char) Integer.parseInt(hex.substring(i, i+2), 16);
for (int i = 0; i < cs.length; i++)
if (cs[i] < ' ' || cs[i] > '~') // printable ASCII
cs[i] = '.';
System.out.println(new String(cs));
}
}
which outputs
p./gl........8
However, my guess is that you're better off using a library that can parse pcaps (I mentioned one earlier, it looks like http://jpcap.sourceforge.net might also work), since just getting that hex string in the first place required opening Wireshark. You can write the code yourself to pull those values from the (binary) pcap file, but projects already exist to do that.
Related
I'm currently working on a small challenge, trying to figure out how an unnamed encryption algorithm works. The original algorithm looks like this:
public final String a(byte[] original)
{
this.a = original.length;
byte[] solution = new byte[8];
int i = 0;
int base = 13;
for (int si = 0; si < 8; si++)
{
for (int oi = 0; oi < a; oi++)
{
byte current = original[oi];
solution[i] = ((byte)(solution[i] + (current ^ base)));
base = (base ^ i) + solution[i];
i = (i + 1) % 8;
}
}
char[] result = new char[8];
for (int n = 0; n < 8; n++) {
result[n] = ((char)((solution[n] & 0x3F) + 48));
}
return String.valueOf(result);
}
So every string that gets passed to this function as a byte[] array will be encoded into a 8-char somewhat cryptic text. I've found out other things about this:
The encoded characters in the char[] result always have literals with values between 48 and 111 (0x3F + 48).
When decoding, the first step would be subtracting 48 and then undo the & operation. Since 0x3F equals the binary representation 111111, the value of the original byte is one of 4 possibilities:
00xxxxxx: the missing 2 bits were both zero.
01xxxxxx: the lower addressed bit of both was one.
10xxxxxx: the higher addressed bit of both was one.
11xxxxxx: both of them were one.
Meaning, it could be one of four characters. I initially thought about reversing the algorithm, but I'm asking you if this is even possible for this kind of algorithm. I tried it and came this far:
public static String b(String encrypted) {
byte[][] matrix = new byte[4][20];
byte[] word = encrypted.getBytes();
for(int i = 0; i < 4; i++) {
for(int j = 0; j < word.length; j++) {
byte tmp = (byte)(word[i] - 48);
matrix[i][j] = (byte)(tmp + i);
}
}
}
I currently subtract 48 and insert all 4 possibilities into a 2D-array. But im stuck solving the nested for loop, especially the variables i and base are hard to find out. The only information I have is the encrypted word and the fact that the original word was 20 literals long at MAX (Hence the [4][20] dimensions).
The encryption doesn't look familiar to me, which leaves me no options to look for the name of this algorithm.
If it is possible to reverse this algorithm, what would my next step be?
No, that obviously can't be reversible in the general case.
There are effectively 40 bits of information in the output (eight bytes, at 5 bits each -- & 0x1F limits each one to five bits). This means that there are only 240 possible outputs; there are far more possible inputs than that.
If there are some constraints on the input -- for instance, if its length is known to be short -- it might be possible to make some inferences about that. However, you haven't stated any constraints, so…
I'm trying to implement the tail program and want to print the last n bytes of a file. I've used a RandomAccessFile variable to store the data from the text file. When I try to retrieve the data and print it to the console, I'm getting something like this:
-n1
65109710979710979710810979710810510510979710910659711010510979711410011897114107109797114100119111108102106597114111110
How does on properly retrieve the data from the byte array?
This is my code:
RandomAccessFile raf = new RandomAccessFile(file, "r");
byte[] b = new byte[n];
raf.readFully(b, 0, n);
for (int i = 0; i < n; i++) {
System.out.print(b[i]);
}
You are printing the byte value. To convert e.g. an array of bytes to a String that you can print on System.out.println try the following:
System.out.println(new String(b));
If you wish to convert each byte (as in your loop) to a printable charyou can do the following conversion:
for (int i = 0; i < 10; i++) {
char c = (char) (b[i] & 0xFF);
System.out.print(c);
}
A byte is simply one byte in size (8 bits) whereas a char in Java i 16 bits (2 bytes). Therefore the printed bytes does not make sense, it is not an entire character.
See this link for more info.
I know that ENCODED are the bytes array, but what is MASK, what are his values?
var DECODED = "";
for (var i = 0; i < ENCODED.length; i++) {
DECODED[i] = ENCODED[i] ^ MASK[i % 4];
}
I've found this example on the web, the question is how can I know what are the MASK values?
any hint or links please? but in the google examples I find only this type of code, but I wish to see explicitly the MASK values, any help please
pstream = new BufferedWriter(new OutputStreamWriter(csocket.getOutputStream(), StandardCharsets.UTF_8));
char[] buff = new char[4];
pstream.read(buf);
//now buf have that masks?
Right above that code snippet it says:
If the MASK bit was set (and it should be, for client-to-server messages), read the next 4 octets (32 bits); this is the masking key.
You can find the MASK bit in the data frame format description.
So the pseudocode could be extended to
var LEN = decodeLength(buffer);
var MASK = buffer.read(4);
var ENCODED = buffer.read(LEN);
var DECODED = new Buffer(LEN);
for (var i = 0; i < ENCODED.length; i++) {
DECODED[i] = ENCODED[i] ^ MASK[i % 4];
}
How to convert string into bits(not bytes) or array of bits in Java(i will do some operations later) and how to convert into array of ints(every 32 bits turn into the int and then put it into the array? I have never done this kind of conversion in Java.
String->array of bits->(some operations I'll handle them)->array of ints
ByteBuffer bytes = ByteBuffer.wrap(string.getBytes(charset));
// you must specify a charset
IntBuffer ints = bytes.asIntBuffer();
int numInts = ints.remaining();
int[] result = new int[numInts];
ints.get(result);
THIS IS THE ANSWER
String s = "foo";
byte[] bytes = s.getBytes();
StringBuilder binary = new StringBuilder();
for (byte b : bytes)
{
int val = b;
for (int i = 0; i < 8; i++)
{
binary.append((val & 128) == 0 ? 0 : 1);
val <<= 1;
}
// binary.append(' ');
}
System.out.println("'" + s + "' to binary: " + binary);
You are looking for this:
string.getBytes();
Not list, it's an array but you can use it later on, even to convert it to integers.
Well, maybe you can skip the String to bits conversion and convert directly to an array of ints (if what you want is the UNICODE value of each character), using s.toCharArray() where s is a String variable.
This will convert "abc" to byte and then the code will print "abc" in respective ASCII code (ie. 97 98 99).
byte a[]=new byte[160];
String s="abc";
a=s.getBytes();
for(int i=0;i<s.length();i++)
{
System.out.print(a[i]+" ");
}
May be so (I have no compiler in my current computer and don't test if it work, but it can help you a bit):
String st="this is a string";
byte[] bytes=st.getBytes();
List<Integer> ints=new ArrayList<Integer>();
ints.addAll(bytes);
If compiler fails in
ints.addAll(bytes);
you can replace it with
for (int i=0;i<bytes.length();i++){
ints.add(bytes[i]);
}
and if you want to get exactly array:
ints.toArray();
Note that string is a sequence of chars, and in Java each char data type is a single 16-bit Unicode character. It has a minimum value of '\u0000' (or 0) and a maximum value of '\uffff' (or 65,535 inclusive). In order to get char integer value do this:
String str="test";
String tmp="";
int result[]=new int[str.length()/2+str.length()%2];
int count=0;
for(char c:str.toCharArray()) {
tmp+=Integer.toBinaryString((int)c);
if(tmp.length()==14) {
result[count++]=Integer.valueOf(tmp,2);
//System.out.println(tmp+":"+result[count-1]);
tmp="";
}
}
for(int i:result) {
System.out.print(i+" ");
}
I have two-dimensional array of integers. First index indicates the number of channels. The second one indicates the number of sample in the channel. How can I save this array into the audio file? I know, I have to convert it to byte array, but I have no idea how to do that.
// edit
More info. I already have a class for drawing a waveform. It is here:
http://javafaq.nu/java-example-code-716.html
now I want to cut part of this wave and save it to the new file. So I have to cut part of int[][] samplesContainer, convert it to byte array (I don't know how) and then save it to file with the same format as audioInputStream.
// edit
OK. So the biggest problem is to write inverted function to this one:
protected int[][] getSampleArray(byte[] eightBitByteArray) {
int[][] toReturn = new int[getNumberOfChannels()][eightBitByteArray.length / (2 * getNumberOfChannels())];
int index = 0;
//loop through the byte[]
for (int t = 0; t < eightBitByteArray.length;) {
//for each iteration, loop through the channels
for (int a = 0; a < getNumberOfChannels(); a++) {
//do the byte to sample conversion
//see AmplitudeEditor for more info
int low = (int) eightBitByteArray[t];
t++;
int high = (int) eightBitByteArray[t];
t++;
int sample = (high << 8) + (low & 0x00ff);
if (sample < sampleMin) {
sampleMin = sample;
} else if (sample > sampleMax) {
sampleMax = sample;
}
//set the value.
toReturn[a][index] = sample;
}
index++;
}
return toReturn;
}
I don't understand why there is second incrementation of t, after high. I also have no idea how can i get high and low from sample.
The code you posted reads a sample stream, byte by byte, into the samples array. The code assumes that, in the stream, every two 8-bit bytes form a 16-bit sample, and that there is one sample for each of the NumOfChannels channels.
So, given an array of samples like the one returned by that code,
int[][] samples;
and a byte array for streaming,
byte[] stream;
you might build the converse stream of bytes this way
for (int i=0; i<NumOfSamples; i++) {
for (int j=0; j<NumOfChannels; j++) {
int sample=samples[i][j];
byte low = (byte) (sample & 0xff) ;
byte high = (byte) ((sample & 0xff00 ) >> 8);
stream[((i*NumOfChannels)+j)*2] = low;
stream[(((i*NumOfChannels)+j)*2)+1] = high;
}
}