Need help reverse engineering a CRC16 - reverse-engineering

I'm trying to connect to the Safecom TA-810 (badge/registration system) to automate the process of calculating how long employee's have worked each day. Currently this is done by:
Pulling the data into the official application
Printing a list of all 'registrations'
Manually entering the values from the printed lists into our HR application
This is a job that can take multiple hours which we'd like to see automated. So far the official tech support has been disappointing and refused to share any details.
Using wireshark I have been capturing the UDP transmissions and have pretty much succeeded in understanding how the protocol is built up. I'm only having issues with what i suppose is a CRC field. I don't know how it is calculated (CRC type and parameters) and using which fields ...
This is how a message header looks like:
D0 07 71 BC BE 3B 00 00
D0 07 - Message type
71 BC - This i believe is the CRC
BE 3B - Some kind of session identifier. Stays the same for every message after the initial message (initial message has '00 00' as value)
00 00 - Message number. '01 00', '02 00', '03 00'
Some examples:
Header only examples
E8 03 17 FC 00 00 00 00 -> initial request (#0, no session nr)
D0 07 71 BC BE 3B 00 00 -> Initial response (#0, device sends a session nr)
4C 04 EF BF BE 3B 06 00 -> Message #6, still using the same session # as the initial response
Larger example, which has data
0B 00 07 E1 BE 3B 01 00 7E 45 78 74 65 6E 64 46 6D 74
I've also been trying to figure this out by reading the disassembled code from the original application. The screenshot below happens before the socket.sendto and seems to be related.
Any help will be extremely appreciated.
EDIT: Made some success with debugging the application using ollydbg. The CRC appears in register (reversed) EDX at the selected line in the following screenshot.

Take a look at CRC RevEng. If you can correctly identify the data that the CRC is operating on and the location of the CRC, you should be able to determine the CRC parameters. If it is a CRC.

I've managed to create a php script that does the CRC calculation by debugging the application using OllyDbg.
The CRC is calculated by Adding up every 2 bytes (every short). if the result is larger than a short, the 'most significant short' is added to the 'least significant short' until the result fits in a short. Finally, the CRC (short) is inverted.
I'll add my php script for completeness:
<?php
function CompareHash($telegram)
{
$telegram = str_replace(" ", "", $telegram);
$telegram_crc = substr($telegram, 4, 4);
$telegram = str_replace($telegram_crc, "0000", $telegram);
echo "Telegram: ", $telegram, ', Crc: ', $telegram_crc, ' (', hexdec($telegram_crc), ')<br />';
$crc = 0;
$i = 0;
while ($i < strlen($telegram))
{
$short = substr($telegram, $i, 4);
if (strlen($short) < 4) $short = $short . '00';
$crc += hexdec($short);
$i += 4;
}
echo "Crc: ", $crc, ', inverse: ', ~$crc;
// Region "truncate CRC to Int16"
while($crc > hexdec('FFFF'))
{
$short = $crc & hexdec ('FFFF');
// Region "unsigned shift right by 16 bits"
$crc = $crc >> 16;
$crc = $crc & hexdec ('FFFF');
// End region
$crc = $short + $crc;
}
// End region
// Region "invert Int16"
$crc = ~$crc;
$crc = $crc & hexdec ('FFFF');
// End region
echo ', shifted ', $crc;
if (hexdec($telegram_crc) == $crc)
{
echo "<br />MATCH!!! <br />";
}
else
{
echo "<br />failed .... <br />";
}
}
$s1_full = "E8 03 17 FC 00 00 00 00";
$s2_full = "D0 07 71 BC BE 3B 00 00";
$s3_full = "D0 07 4E D4 E1 23 00 00";
$s4_full = "D0 07 35 32 BE 3B 07 00 7E 44 65 76 69 63 65 4E 61 6D 65 3D 54 41 38 31 30 00";
$s5_full = "0B 00 39 6C BE 3B 05 00 7E 52 46 43 61 72 64 4F 6E";
CompareHash($s1_full);
CompareHash($s2_full);
CompareHash($s3_full);
CompareHash($s4_full);
CompareHash($s5_full);
?>
Thanks for the feedback!

Related

ASC 122U NFC Reader compatible with EMV Contactless Cards

I am trying to read a EMV card using an APDU Command, however it seems the ACR122U external reader is blocking the APDU Command.
Select Command:
APDU-C -> 00 A4 04 00 0E 32 50 41 59 2E 53 59 53 2E 44 44 46 30 31 0E
APDU-R <- Error no response
Is it possible that the ACR122U reader is blocking the command ?
You want to SELECT FILE 1PAY.SYS.DDF01,
"Payment System Environment (PSE)"
To get the PSE directory and the card should response with Application Identifier (AID). but you set the LE=0E replace it to "00" .
Corrected APDU =>
PPSE = '00 a4 04 00 0e 32 50 41 59 2e 53 59 53 2e 44 44 46 30 31 00'
if The selection failed then the ADF doesn't exist (SW1/SW2=6A82)
if the selection is true then Application Identifier (AID) start command
Possible AID's:
A0000000031010
A0000000032020
A0000000041010
A0000000043060
AIDPrefix ='00 a4 04 00 07'

How to display an image from mysql using Express

I have a sql table 'animals' where there are blobs images. I found out how to upload images but not how to display them.
I would like to display the image which is called 'Dog' in my table.
Here is my code, where I print the result of my blob img.
let sql = 'SELECT * FROM animals WHERE file_name=\'Dog\''
connection.query(sql, (err,result) => {
console.log(result[0].img)
})
Here is the result of my code:
<Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 01 00 01 00 00 ff db 00 84 00 09 06 07 13 12 12 15 13 13 13 16 16 15 15 18 18 17 16 18 15 17 15 17 17 16 ... >
Is there is any way to display that picture?
Thank you.
You can use the Fetch API to get the resource on your web page.
You can display the image like this :
fetch('http://localhost:1234/your_api')
.then(function(response) {
return response.blob();
})
.then(function(myBlob) {
var objectURL = URL.createObjectURL(myBlob);
document.querySelector("#databaseimage").src = objectURL;
});
In HTML :
<img id="databaseimage"/>
You can read more about Fetch API here :
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

CompileError: WebAssembly.compile()

I am trying to execute basic C code of calculating factorial in WebAssembly and when I am loading WASM file in Google Chrome ( 57.0.2987.98) I am getting
CompileError: WebAssembly.compile():
Wasm decoding failedResult = expected magic word 00 61 73 6d,
found 30 30 36 31 #+0`
C Code :
double fact(int i) {
long long n = 1;
for (;i > 0; i--) {
n *= i;
}
return (double)n;
}
WAST :
(module
(table 0 anyfunc)
(memory $0 1)
(export "memory" (memory $0))
(export "_Z4facti" (func $_Z4facti))
(func $_Z4facti (param $0 i32) (result f64)
(local $1 i64)
(local $2 i64)
(block $label$0
(br_if $label$0
(i32.lt_s
(get_local $0)
(i32.const 1)
)
)
(set_local $1
(i64.add
(i64.extend_s/i32
(get_local $0)
)
(i64.const 1)
)
)
(set_local $2
(i64.const 1)
)
(loop $label$1
(set_local $2
(i64.mul
(get_local $2)
(tee_local $1
(i64.add
(get_local $1)
(i64.const -1)
)
)
)
)
(br_if $label$1
(i64.gt_s
(get_local $1)
(i64.const 1)
)
)
)
(return
(f64.convert_s/i64
(get_local $2)
)
)
)
(f64.const 1)
)
)
WASM Compiled Code :
0061 736d 0100 0000 0186 8080 8000 0160
017f 017c 0382 8080 8000 0100 0484 8080
8000 0170 0000 0583 8080 8000 0100 0106
8180 8080 0000 0795 8080 8000 0206 6d65
6d6f 7279 0200 085f 5a34 6661 6374 6900
000a c380 8080 0001 bd80 8080 0001 027e
0240 2000 4101 480d 0020 00ac 4201 7c21
0142 0121 0203 4020 0220 0142 7f7c 2201
7e21 0220 0142 0155 0d00 0b20 02b9 0f0b
4400 0000 0000 00f0 3f0b
`
Code executed in Chrome :
async function load(){
let binary = await fetch('https://flinkhub.com/t.wasm');
let bytes = await binary.arrayBuffer();
console.log(bytes);
let module = await WebAssembly.compile(bytes);
let instance = await WebAssembly.Instance(module);
}
load().then(instance => console.log(instance.exports.fact(3)));
Can anyone help me out, I have been stuck on this for a whole day and not able to understand what is going wrong.
I used WebAssembly Explorer to to get the WAST and WASM code.
Using the WebAssembly Explorer's download capability you reference, I get the following file (as seen with hexdump):
0000000 00 61 73 6d 01 00 00 00 01 86 80 80 80 00 01 60
0000010 01 7f 01 7c 03 82 80 80 80 00 01 00 04 84 80 80
0000020 80 00 01 70 00 00 05 83 80 80 80 00 01 00 01 06
0000030 81 80 80 80 00 00 07 95 80 80 80 00 02 06 6d 65
0000040 6d 6f 72 79 02 00 08 5f 5a 34 66 61 63 74 69 00
0000050 00 0a c3 80 80 80 00 01 bd 80 80 80 00 01 02 7e
0000060 02 40 20 00 41 01 48 0d 00 20 00 ac 42 01 7c 21
0000070 01 42 01 21 02 03 40 20 02 20 01 42 7f 7c 22 01
0000080 7e 21 02 20 01 42 01 55 0d 00 0b 20 02 b9 0f 0b
0000090 44 00 00 00 00 00 00 f0 3f 0b
000009a
That's a valid .wasm binary which starts with the magic 00 61 73 6d a.k.a. \0asm. According to the error message you get, your file starts with 30 30 36 31 which isn't valid.
Double-check the .wasm file you have.
Decoding 30 30 36 31 as ASCII gives 0061 which seems to be your problem: you're loading the textual version of your hex file. Sure enough, the URL you provide (https://flinkhub.com/t.wasm) contains the following content as-is (I didn't hexdump it! It's ASCII):
0061 736d 0100 0000 0186 8080 8000 0160
017f 017c 0382 8080 8000 0100 0484 8080
8000 0170 0000 0583 8080 8000 0100 0106
8180 8080 0000 0795 8080 8000 0206 6d65
6d6f 7279 0200 085f 5a34 6661 6374 6900
000a c380 8080 0001 bd80 8080 0001 027e
0240 2000 4101 480d 0020 00ac 4201 7c21
0142 0121 0203 4020 0220 0142 7f7c 2201
7e21 0220 0142 0155 0d00 0b20 02b9 0f0b
4400 0000 0000 00f0 3f0b
I'm guessing you overwrote the file saved from the Explorer.
I solved this by setting GOARCH and GOOS environment variable correctly in zsh shell of mac before generating wasm object. Looks like go compiler does not recognize both these variables unless you explosively export them as a global variable in the parent shell. I simply exported both variables and run the compiler.
% export GOARCH=wasm
% export GOOS=js
% go build -o hello.wasm hello.go
I am not sure about your system, but I am using react and esbuild.wasm where while running the below code I was getting error.
const service = await esbuild.startService({
worker: true,
wasmURL: "/esbuild.wasm/esbuild.wasm"
})
esbuild.wasm is in my public folder along with node_module.
So I corrected the url which is wasmURL: "https://unpkg.com/esbuild-wasm#0.8.27/esbuild.wasm" and now it is working.
30 30 36 31 is the hex dump of the string "0061" which is the start of the hex dump of your wasm binary. Did you somehow fetch the textual hexdump instead of the actual binary?
In general, this error means that instead of the binary .wasm file your browser received something else. That can be a error page generated by the web server or the same .wasm but corrupted somehow. I recommend to open your browser Developer Tools, go to Network tab, Refresh the page and look at the .wasm resource request and response.

How can I implement server side SMTP STARTTLS?

I am trying to implement a simple SMTP server using Vala and GLib + GIO.
Plain text communication is no problem so far, but when it comes to TLS using STARTTLS things get harder.
This is the code I have so far:
const string appname = "vsmtpd";
const string hostname = "myserver";
const uint16 listenport = 10025;
const string keyfile = "vsmtpd.key";
const string certfile = "vsmtpd.crt";
// TODO: Parse EHLO instead of constant string
const string username = "myclient";
void process_request_plain (InputStream input, OutputStream output) throws Error {
output.write (#"220 $hostname ESMTP $appname\n".data);
var data_in = new DataInputStream (input);
string line;
while ((line = data_in.read_line (null)) != null) {
stdout.printf ("%s\n", line);
line = line.chomp ();
if (line.substring (0, 5) == "EHLO ") {
output.write (#"250-$hostname Hello $username\n".data);
output.write ("250 STARTTLS\n".data);
}
else if (line == "STARTTLS") {
output.write ("220 Go ahead\n".data);
break;
}
else {
output.write ("502 Command not implemented\n".data);
}
}
}
int main () {
try {
TlsCertificate cert = new TlsCertificate.from_files
(certfile, keyfile);
var service = new SocketService ();
service.add_inet_port (listenport, null);
service.start ();
while (true) {
SocketConnection conn = service.accept (null);
process_request_plain (conn.input_stream, conn.output_stream);
TlsServerConnection tlsconn = TlsServerConnection.#new (conn, cert);
assert_nonnull (tlsconn);
// TODO: Is this neccessary?
tlsconn.accept_certificate.connect ((peer_cert, errors) => {
stdout.printf ("TLS accepting peer cert\n");
return true;
});
try {
tlsconn.handshake ();
stdout.printf ("TLS handshake ok\n");
} catch (Error e) {
stdout.printf ("TLS handshake failed\n");
stderr.printf ("%s\n", e.message);
}
}
} catch (Error e) {
stderr.printf ("%s\n", e.message);
}
return 0;
}
Given a valid SSL certificate in vsmtpd.key and vsmtpd.crt (which I generated with openssl req -x509 -newkey rsa:2048 -keyout vsmtpd.key -out vsmtpd.pem -days 365 -nodes) I start the program and I also run this OpenSSL command to test STARTTLS:
openssl s_client -connect localhost:10025 -starttls smtp -debug
The output from my program is:
EHLO openssl.client.net
STARTTLS
TLS handshake failed
Stream is already closed
The output from OpenSSL is:
CONNECTED(00000003)
read from 0x6ae470 [0x6af050] (4096 bytes => 26 (0x1A))
0000 - 32 32 30 20 6d 79 73 65-72 76 65 72 20 45 53 4d 220 myserver ESM
0010 - 54 50 20 76 73 6d 74 70-64 0a TP vsmtpd.
write to 0x6ae470 [0x6b0060] (25 bytes => 25 (0x19))
0000 - 45 48 4c 4f 20 6f 70 65-6e 73 73 6c 2e 63 6c 69 EHLO openssl.cli
0010 - 65 6e 74 2e 6e 65 74 0d-0a ent.net..
read from 0x6ae470 [0x6af050] (4096 bytes => 28 (0x1C))
0000 - 32 35 30 2d 6d 79 73 65-72 76 65 72 20 48 65 6c 250-myserver Hel
0010 - 6c 6f 20 6d 79 63 6c 69-65 6e 74 0a lo myclient.
read from 0x6ae470 [0x6af050] (4096 bytes => 13 (0xD))
0000 - 32 35 30 20 53 54 41 52-54 54 4c 53 0a 250 STARTTLS.
write to 0x6ae470 [0x7ffdb4aea9e0] (10 bytes => 10 (0xA))
0000 - 53 54 41 52 54 54 4c 53-0d 0a STARTTLS..
read from 0x6ae470 [0x6a13a0] (8192 bytes => 13 (0xD))
0000 - 32 32 30 20 47 6f 20 61-68 65 61 64 0a 220 Go ahead.
write to 0x6ae470 [0x6aefa0] (204 bytes => 204 (0xCC))
0000 - 16 03 01 00 c7 01 00 00-c3 03 03 0e ac 05 35 45 ..............5E
0010 - db 95 f6 a7 37 55 d8 ca-14 d7 5f 8e 6a 62 08 50 ....7U...._.jb.P
0020 - c9 81 b7 55 75 a8 4c 17-c0 a1 53 00 00 76 00 a5 ...Uu.L...S..v..
0030 - 00 a3 00 a1 00 9f 00 6b-00 6a 00 69 00 68 00 39 .......k.j.i.h.9
0040 - 00 38 00 37 00 36 00 88-00 87 00 86 00 85 00 9d .8.7.6..........
0050 - 00 3d 00 35 00 84 00 a4-00 a2 00 a0 00 9e 00 67 .=.5...........g
0060 - 00 40 00 3f 00 3e 00 33-00 32 00 31 00 30 00 9a .#.?.>.3.2.1.0..
0070 - 00 99 00 98 00 97 00 45-00 44 00 43 00 42 00 9c .......E.D.C.B..
0080 - 00 3c 00 2f 00 96 00 41-00 07 00 05 00 04 00 16 .<./...A........
0090 - 00 13 00 10 00 0d 00 0a-00 15 00 12 00 0f 00 0c ................
00a0 - 00 09 00 ff 02 01 00 00-23 00 23 00 00 00 0d 00 ........#.#.....
00b0 - 16 00 14 06 01 06 02 05-01 05 02 04 01 04 02 03 ................
00c0 - 01 03 02 02 01 02 02 00-0f 00 01 01 ............
read from 0x6ae470 [0x6b4500] (7 bytes => -1 (0xFFFFFFFFFFFFFFFF))
write:errno=104
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 80 bytes and written 239 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
---
What I understand from the output my program closes the connection before the TLS handshake can complete. (I also tried using Thunderbird and Claws Mail)
What am I doing wrong here?
PS: I couldn't find any example on how to use GTLsServerConnection in a STARTTLS situation.
Update:
I tried -ssl2, -ssl3, -tls1, -tls1_1, -tls1_2 options of OpenSSL which also don't work.
openssl s_client -connect localhost:10025 -starttls smtp -state
yields:
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:SSLv2/v3 write client hello A
SSL_connect:error in SSLv2/v3 read server hello A
write:errno=104
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 100 bytes and written 239 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
---
So the client sends "client hello A", but the server doesn't send a correct "server hello A".
As an alternative you can also try gnutls-cli --crlf --starttls-proto=smtp --port 10025 localhost.
The output from GNUTLS_DEBUG_LEVEL=11 ./vsmtpd is:
gnutls[2]: Enabled GnuTLS logging...
gnutls[2]: Intel SSSE3 was detected
gnutls[2]: Intel AES accelerator was detected
gnutls[2]: Intel GCM accelerator was detected
gnutls[2]: Enabled GnuTLS logging...
gnutls[2]: Intel SSSE3 was detected
gnutls[2]: Intel AES accelerator was detected
gnutls[2]: Intel GCM accelerator was detected
gnutls[3]: ASSERT: x509_b64.c:299
gnutls[9]: Could not find '-----BEGIN RSA PRIVATE KEY'
gnutls[3]: ASSERT: x509_b64.c:299
gnutls[9]: Could not find '-----BEGIN DSA PRIVATE KEY'
gnutls[3]: ASSERT: x509_b64.c:299
gnutls[9]: Could not find '-----BEGIN EC PRIVATE KEY'
gnutls[3]: ASSERT: privkey.c:503
gnutls[2]: Falling back to PKCS #8 key decoding
EHLO openssl.client.net
STARTTLS
gnutls[5]: REC[0xfa67e0]: Allocating epoch #0
gnutls[3]: ASSERT: gnutls_constate.c:586
gnutls[5]: REC[0xfa67e0]: Allocating epoch #1
gnutls[3]: ASSERT: gnutls_buffers.c:1138
gnutls[10]: READ: -1 returned from 0xfa4120, errno=0 gerrno=5
gnutls[3]: ASSERT: gnutls_buffers.c:364
gnutls[3]: ASSERT: gnutls_buffers.c:572
gnutls[3]: ASSERT: gnutls_record.c:1058
gnutls[3]: ASSERT: gnutls_record.c:1179
gnutls[3]: ASSERT: gnutls_buffers.c:1392
gnutls[3]: ASSERT: gnutls_handshake.c:1428
gnutls[3]: ASSERT: gnutls_handshake.c:3098
gnutls[3]: ASSERT: gnutls_db.c:334
TLS handshake failed
Stream is already closed
gnutls[5]: REC[0xfa67e0]: Start of epoch cleanup
gnutls[5]: REC[0xfa67e0]: End of epoch cleanup
gnutls[5]: REC[0xfa67e0]: Epoch #0 freed
gnutls[5]: REC[0xfa67e0]: Epoch #1 freed
The problem is hidden somewhere in the implementation of DataInputStream.
Once I removed it and used the following replacement for read_line () instead, it works just fine.
string? read_line (InputStream input) throws Error {
var buffer = new uint8[1];
var sb = new StringBuilder ();
buffer[0] = '\0';
while (buffer[0] != '\n') {
input.read (buffer);
sb.append_c ((char) buffer[0]);
}
return (string) sb.data;
}
void process_request_plain (InputStream input, OutputStream output) throws Error {
output.write (#"220 $hostname ESMTP $appname\n".data);
string line;
while ((line = read_line (input)) != null) {
stdout.printf ("%s\n", line);
line = line.chomp ();
if (line.substring (0, 5) == "EHLO ") {
output.write (#"250-$hostname Hello $username\n".data);
output.write ("250 STARTTLS\n".data);
}
else if (line == "STARTTLS") {
output.write ("220 Go ahead\n".data);
break;
}
else {
output.write ("502 Command not implemented\n".data);
}
}
}

MySQL COM_EXECUTE_STMT fails with error but the error does not make sense

I'm sending a COM_EXECUTE_STMT message and the server always returns an:
Error 1048 - #23000 - Column 'number_tinyint' cannot be null
The query is like this:
insert into numbers (
number_tinyint,
number_smallint,
number_mediumint,
number_int,
number_bigint,
number_decimal,
number_float,
number_double
) values
(
?, 679, 778, 875468, 100007654, 198.657809, 432.8, ?)
And what I send in is:
0: 18 00 00 00 17 01 00 00 . . . . . . . .
1: 00 00 01 00 00 00 00 00 . . . . . . . .
2: 01 01 05 0a 29 5c 8f c2 . . . . ) \ . .
3: f5 b0 58 40 . . X #
And simplified for reading:
18 00 00 - size
00 - sequence
17 - type
01 00 00 00 - statement id
00 - flags
01 00 00 00 - iteration-count
00 00 - null bitmap
01 - new params bound flag
01 - byte type
05 - double type
0a - byte value - 10
29 5c 8f c2 f5 b0 58 40 - double value
The statement parameters are 10 (for the tinyint column) and 98.765 (for the double column). From what I can see the message is encoded correctly but it always fails for some reason (at least from what the documentation says)
Am I missing something in here?
From the documentation to which you've linked:
payload:
[ deletia ]
n NULL-bitmap, length: (num-params+7)/8
Therefore, with two parameters in your case, the NULL-bitmap should have a length of (2+7)/8 = 1 byte, whereas you currently have a 2-byte bitmap.