How can I process the header of an exe when disassembling with iced_x86? - x86-64

I want to disassemble a list of executables with an output format for the instructions that I can customize. As a prior web developer, iced-x86 with Node.js seems like an easy way to start. I want to use this.
The code I'm using is exactly what's listed on the documentation for iced-x86:
Disassemble (decode and format instructions), although I'm loading the Uint8Array from my own exe and set the RIP to 0x0, I'm not sure how this value should be decided - it seems like an arbitrary equivalent to uint64_t exampleRip = 0x00007FFAC46ACDA4:
// iced-x86 features needed: --features "decoder nasm"
const { Decoder, DecoderOptions, Formatter, FormatterSyntax } = require("iced-x86");
/*
This code produces the following output:
00007FFAC46ACDA4 48895C2410 mov [rsp+10h],rbx
00007FFAC46ACDA9 4889742418 mov [rsp+18h],rsi
00007FFAC46ACDAE 55 push rbp
00007FFAC46ACDAF 57 push rdi
00007FFAC46ACDB0 4156 push r14
00007FFAC46ACDB2 488DAC2400FFFFFF lea rbp,[rsp-100h]
00007FFAC46ACDBA 4881EC00020000 sub rsp,200h
00007FFAC46ACDC1 488B0518570A00 mov rax,[rel 7FFA`C475`24E0h]
00007FFAC46ACDC8 4833C4 xor rax,rsp
00007FFAC46ACDCB 488985F0000000 mov [rbp+0F0h],rax
00007FFAC46ACDD2 4C8B052F240A00 mov r8,[rel 7FFA`C474`F208h]
00007FFAC46ACDD9 488D05787C0400 lea rax,[rel 7FFA`C46F`4A58h]
00007FFAC46ACDE0 33FF xor edi,edi
*/
const exampleBitness = 64;
const exampleRipLo = 0xC46ACDA4;
const exampleRipHi = 0x00007FFA;
const exampleCode = new Uint8Array([
0x48, 0x89, 0x5C, 0x24, 0x10, 0x48, 0x89, 0x74, 0x24, 0x18, 0x55, 0x57, 0x41, 0x56, 0x48, 0x8D,
0xAC, 0x24, 0x00, 0xFF, 0xFF, 0xFF, 0x48, 0x81, 0xEC, 0x00, 0x02, 0x00, 0x00, 0x48, 0x8B, 0x05,
0x18, 0x57, 0x0A, 0x00, 0x48, 0x33, 0xC4, 0x48, 0x89, 0x85, 0xF0, 0x00, 0x00, 0x00, 0x4C, 0x8B,
0x05, 0x2F, 0x24, 0x0A, 0x00, 0x48, 0x8D, 0x05, 0x78, 0x7C, 0x04, 0x00, 0x33, 0xFF
]);
const hexBytesColumnByteLength = 10;
const decoder = new Decoder(exampleBitness, exampleCode, DecoderOptions.None);
// You have to enable the bigint feature to get i64/u64 APIs, not all browsers support BigInt
decoder.ipLo = exampleRipLo;
decoder.ipHi = exampleRipHi;
// This decodes all bytes. There's also `decode()` which decodes the next instruction,
// `decodeInstructions(count)` which decodes `count` instructions and `decodeOut(instruction)`
// which overwrites an existing instruction.
const instructions = decoder.decodeAll();
// Create a nasm formatter. It supports: Masm, Nasm, Gas (AT&T) and Intel (XED).
// There's also `FastFormatter` which uses less code (smaller wasm files).
// const formatter = new FastFormatter();
const formatter = new Formatter(FormatterSyntax.Nasm);
// Change some options, there are many more
formatter.digitSeparator = "`";
formatter.firstOperandCharIndex = 10;
// Format the instructions
instructions.forEach(instruction => {
const disasm = formatter.format(instruction);
// Eg. "00007FFAC46ACDB2 488DAC2400FFFFFF lea rbp,[rsp-100h]"
let line = ("0000000" + instruction.ipHi.toString(16)).substr(-8).toUpperCase() +
("0000000" + instruction.ipLo.toString(16)).substr(-8).toUpperCase();
line += " ";
const startIndex = instruction.ipLo - exampleRipLo;
exampleCode.slice(startIndex, startIndex + instruction.length).forEach(b => {
line += ("0" + b.toString(16)).substr(-2).toUpperCase();
});
for (let i = instruction.length; i < hexBytesColumnByteLength; i++)
line += " ";
line += " ";
line += disasm;
console.log(line);
});
// Free wasm memory
instructions.forEach(instruction => instruction.free());
formatter.free();
decoder.free();
Meanwhile, I'm also disassembling the same file with Ghidra to check my work.
Ghidra outputs the correct disassembly of the header:
//
// Headers
// ram:00400000-ram:004001ff
//
assume DF = 0x0 (Default)
IMAGE_DOS_HEADER_00400000 XREF[1]: 004000b4(*)
00400000 4d 5a 90 IMAGE_DO
00 03 00
00 00 04
00400000 4d 5a char[2] "MZ" e_magic
00400002 90 00 dw 90h e_cblp Bytes of last page
00400004 03 00 dw 3h e_cp Pages in file
00400006 00 00 dw 0h e_crlc Relocations
00400008 04 00 dw 4h e_cparhdr Size of header in
0040000a 00 00 dw 0h e_minalloc Minimum extra para
0040000c ff ff dw FFFFh e_maxalloc Maximum extra para
0040000e 00 00 dw 0h e_ss Initial (relative)
00400010 b8 00 dw B8h e_sp Initial SP value
00400012 00 00 dw 0h e_csum Checksum
00400014 00 00 dw 0h e_ip Initial IP value
00400016 00 00 dw 0h e_cs Initial (relative)
00400018 40 00 dw 40h e_lfarlc File address of re
0040001a 00 00 dw 0h e_ovno Overlay number
While iced_x86 outputs the following, clearing not correctly handling the header:
0000000000000000 4D5A pop r10
0000000000000002 90 nop
0000000000000003 0003 add [rbx],al
0000000000000005 0000 add [rax],al
0000000000000007 000400 add [rax+rax],al
000000000000000A 0000 add [rax],al
000000000000000C FFFF (bad)
000000000000000E 0000 add [rax],al
0000000000000010 B800000000 mov eax,0
0000000000000015 0000 add [rax],al
0000000000000017 004000 add [rax],al
000000000000001A 0000 add [rax],al
I'm newly learning Assembly; I don't know how the header data needs to be disassembled differently from the the rest of the instructions. How can I handle this? Is there a feature of iced_x86 I should be using?
What I've tried:
I'm looking through documentation on the topic, and found this representation in C:
struct DOS_Header
{
// short is 2 bytes, long is 4 bytes
char signature[2] = { 'M', 'Z' };
short lastsize;
short nblocks;
short nreloc;
short hdrsize;
short minalloc;
short maxalloc;
void *ss; // 2 byte value
void *sp; // 2 byte value
short checksum;
void *ip; // 2 byte value
void *cs; // 2 byte value
short relocpos;
short noverlay;
short reserved1[4];
short oem_id;
short oem_info;
short reserved2[10];
long e_lfanew; // Offset to the 'PE\0\0' signature relative to the beginning of the file
}
Which seems straightforward enough. But I'm still unsure whether I need to write code for this in the Node.js script, or if the iced_x86 library supports it already.

Related

Sending Midi Sysex messages in C#

I'm trying to figure out how to make a simple Winform app that sends a SysEx MIDI message when I click a button, so button 1 sends:-
F0 7F 22 02 50 01 31 00 31 00 31 F7
Button 2 sends:
F0 7F 22 02 50 01 32 00 31 00 31 F7
and so on...
I was able to find lots of info about sending notes and instrument data but nothing really about sysex. I have played with the Sanford reference which seemed to get me closer but still nothing about Sysex usage.
There are various MIDI libraries available, and most support SysEx in one form or another. I've mostly used the managed-midi package although I've used the Sanford package before.
In managed-midi at least, sending a SysEx message is as simple as obtaining an IMidiOutput (usually from a MidiAccessManager) and then calling the Send method. For example:
// You'd do this part just once, of course...
var accessManager = MidiAccessManager.Default;
var portId = access.Outputs.First().Id;
var port = await access.OpenOutputAsync(portId);
// You'd port this part in your button click handler.
// The data is copied from the question, so I'm assuming it's okay...
var message = new byte[] {
0xF0, 0x7F, 0x22, 0x02, 0x50, 0x01,
0x31, 0x00, 0x31, 0x00, 0x31, 0xF7 };
port.Send(message, 0, message.Length, timestamp: 0);

STM32 HID Keyboard

I am trying to use and STM32F0-disco as a keyboard for a Windows PC. I'm having a problem with the characters that are being printed.
The code below waits until the onboard button is pressed then should print the three characters once.
/* USER CODE BEGIN 2 */
USBDelay = USBD_HID_GetPollingInterval(&hUsbDeviceFS);
while (HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == 0);
if (HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == 1) {
HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
buff[0] = 0x00;
buff[2] = 0x04;
buff[3] = 0x05;
buff[4] = 0x06;
USBD_HID_SendReport(&hUsbDeviceFS, buff, 8);
HAL_Delay(USBDelay);
buff[0] = 0x00;
buff[2] = 0x00;
buff[3] = 0x00;
buff[4] = 0x00;
USBD_HID_SendReport(&hUsbDeviceFS, buff, 8);
HAL_GPIO_TogglePin(LD4_GPIO_Port, LD4_Pin);
HAL_Delay(1000);
}
while (HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == 1);
/* USER CODE END 2 */
The problem I'm having is that the only the characters in the first two key positions of the buffer (which would be the third and fourth elements of the array since element one is the modifier and the second element is reserved). Also, instead of printing once, the characters print continuously without stopping.
Based on the LED's I've added for testing purposes, the characters that I want to print don't print until the second USB_SendReport, which should be sending blank characters to stop the printing.
I've made the necessary changes to usbd_hid.c and usbd_hid.h, as well as the Clock configuration and enabling USB and such. I've put my keyboard descriptor below.
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0 // END_COLLECTION
Any ideas?
The USB HID protocol works differently than you assume. If the input report contains multiple pressed keys, the host (your Windows PC) assumes that they have been pressed at the same time. So they can be inserted in any order. And it might also be the reason the third key is not inserted.
So you need to send a separate output report for each key. And after the last report you need to send another empty one (with all 0s) to indicate the keys have been released (as you are already doing). Such an additional report is also needed between two presses of the same key.
The reason the keys are inserted continuously indicates the empty report was not received. Even though the function uses the term send (USBD_HID_SendReport()), the USB protocol works such that the host needs to pick up the input report. And since it is an USB interrupt endpoint, this only happens ever so often. If a report hasn't been picked up yet, USBD_HID_SendReport() does nothing. It not even returns an error.
While querying to polling interval (USBD_HID_GetPollingInterval()) looks ok at first, it's the polling interval declared in the USB endpoint descriptor. However, Windows only supports a few interval values and rounds up to the next supported value. So you have to increase the value.

Is there a way to print the APDU command generated by NFCISO7816APDU

I want to debug the following code and see what is the raw APDU it produces. I mean byte by byte from the header to the Le parameter.
let selectFileAPDU = NFCISO7816APDU(
instructionClass: 0x0C,
instructionCode: 0xA4,
p1Parameter: 0x02,
p2Parameter: 0x0C,
data: selectFileCommand,
expectedResponseLength: -1)

convert 16 bits signed (x2) to 32bits unsigned

I've got a problem with a modbus device :
The device send data in modbus protocol.
I read 4 bytes from the modbus communication that represent a pressure value
I have to convert theses 4 bytes in a unsigned 32bits integer.
There is the modbus documentation :
COMBINING 16bit REGISTERS TO 32bit VALUE
Pressure registers 2 & 3 in SENSOR INPUT REGISTER MAP of this guide are stored as u32 (UNSIGNED 32bit INTEGER)
You can calculate pressure manually :
1) Determine what display you have - if register values are positive skip to step 3.
2) Convert negative register 2 & 3 values from Signed to Unsigned (note: 65536 = 216 ):
(reg 2 value) + 65536* = 35464 ; (reg 3 value) + 65536 = 1
3) Shift register #3 as this is the upper 16 bits: 65536 * (converted reg 3 value) = 65536
4) Put two 16bit numbers together: (converted reg 2 value) + (converted reg 3 value) = 35464 + 65536 = 101000 Pa
Pressure information is then 101000 Pascal.
I don't find it very clear... For exemple, we don't have the 4 bytes that gives this calcul.
So, if anybody has a formula to convert my bytes into a 32bits unsigned int it could be very helpful
You should be able to read your bytes in some kind of type representation (hex, dec, bin, oct...)
let's assume you're receiving the following bytes frame:
in hex:
0x00, 0x06, 0x68, 0xA0
in bin:
0000 0000, 0000 0110, 0110 1000, 1010 0000
all of these are different representation of the same 4 bytes values.
Another thing that you should know is the bytes position (endianess):
If you're frame is transmitted in big endian, you're going to read the bytes in the order that you have them ( so 0x00, 0x06, 0x68, 0xA0 is correct).
If the frame is transmitted in little endian, you need to perform the following operation:
Switch the first 2 bytes with the last 2:
0x68, 0xA0, 0x00, 0x06
and then switch the position between the first and the second byte and the third and the fourth byte:
0xA0, 0x68, 0x06, 0x00
so if your frame is in little endian, the correct frame will be 0xA0, 0x68, 0x06, 0x00.
If you don't know the endianess, assume it's in big endian.
Now you simply have to 'put' your values togheter:
0x00, 0x06, 0x68, 0xA0 will become 0x000668A0
or
0000 0000, 0000 0110, 0110 1000, 1010 0000 will become 00000000000001100110100010100000
Once you have your hex or bin, you can convert your bin to an integer or convert your hex to an integer
Here you can find an interesting tool for converting HEX to float, unit32, int32, int16 in all endianess.
TL;DR
if you can use python, you should use struct:
import struct
frame = [0x00, 0x06, 0x68, 0xA0] # or [0, 6, 104, 160] in dec or [0b00000000, 0b00000110, 0b01101000, 0b10100000] in bin
print struct.unpack('>L', ''.join(map(chr, frame)))[0]

Incorporate V and H wheel to HID report

I have been working with the HID reports and I have been able to compile and run a report for keyboard, 3 button mouse, and 3 button mouse with wheel (vertical only). Right now I have been trying to use the 5 buttons with vertical and horizontal wheel.
So following this
// Input report - 5 bytes
//
// Byte | D7 D6 D5 D4 D3 D2 D1 D0
// ------+---------------------------------------------------------------------
// 0 | 0 0 0 Forward Back Middle Right Left (Buttons)
// 1 | X
// 2 | Y
// 3 | Vertical Wheel
// 4 | Horizontal (Tilt) Wheel
Now I have this report descriptor
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x02, // COLLECTION (Logical)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
// ------------------------------ Buttons
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x05, // USAGE_MAXIMUM (Button 5)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x05, // REPORT_COUNT (5 Buttons)
0x81, 0x02, // INPUT (Data,Var,Abs)
// ------------------------------ Padding
0x75, 0x03, // REPORT_SIZE (8-5buttons 3)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
// ------------------------------ X,Y position
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xa1, 0x02, // COLLECTION (Logical)
// ------------------------------ Vertical wheel res multiplier
0x09, 0x48, // USAGE (Resolution Multiplier)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x35, 0x01, // PHYSICAL_MINIMUM (1)
0x45, 0x04, // PHYSICAL_MAXIMUM (4)
0x75, 0x02, // REPORT_SIZE (2)
0x95, 0x01, // REPORT_COUNT (1)
0xa4, // PUSH
0xb1, 0x02, // FEATURE (Data,Var,Abs)
// ------------------------------ Vertical wheel
0x09, 0x38, // USAGE (Wheel)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x35, 0x00, // PHYSICAL_MINIMUM (0) - reset physical
0x45, 0x00, // PHYSICAL_MAXIMUM (0)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xc0, // END_COLLECTION
0xa1, 0x02, // COLLECTION (Logical)
// ------------------------------ Horizontal wheel res multiplier
0x09, 0x48, // USAGE (Resolution Multiplier)
0xb4, // POP
0xb1, 0x02, // FEATURE (Data,Var,Abs)
// ------------------------------ Padding for Feature report
0x35, 0x00, // PHYSICAL_MINIMUM (0) - reset physical
0x45, 0x00, // PHYSICAL_MAXIMUM (0)
0x75, 0x04, // REPORT_SIZE (4)
0xb1, 0x03, // FEATURE (Cnst,Var,Abs)
// ------------------------------ Horizontal wheel
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
0x0a, 0x38, 0x02, // USAGE (AC Pan)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
Which includes the 5 buttons, vertical and horizontal. This compiles without any issue, but I'm trying to send the following information to test if its working correctly
mouseReport.buttons = 0;
mouseReport.x = 0;
mouseReport.y = 0;
mouseReport.v = 1;
mouseReport.h = 0;
But that 1 on the Vertical wheel byte makes my mouse, click and scroll randomly.
Could anyone tell me what am I missing? I'm using the exact same code, with a different report and 4 bytes, and the scroll works perfect.
Well I found the issue. I was using a struct to send the byte array and it seems that my micro controller didn't like that because it was getting bad resolution, hence why the random movement and clicks. Changing it to an array of unint8_t fixed the issue.