I have a structure:
struct JFIF_HEADER
{
WORD marker[2]; // = 0xFFD8FFE0
WORD length; // = 0x0010
BYTE signature[5]; // = "JFIF\0"
BYTE versionhi; // = 1
BYTE versionlo; // = 1
BYTE xyunits; // = 0
WORD xdensity; // = 1
WORD ydensity; // = 1
BYTE thumbnwidth; // = 0
BYTE thumbnheight; // = 0
};
This is how I read it from the file:
HANDLE file = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
DWORD tmp = 0;
DWORD size = GetFileSize(file, &tmp);
BYTE *DATA = new BYTE[size];
ReadFile(file, DATA, size, &tmp, 0);
JFIF_HEADER header;
memcpy(&header, DATA, sizeof(JFIF_HEADER));
This is how the beginning of my file looks in hex editor:
0xFF 0xD8 0xFF 0xE0 0x00 0x10 0x4A 0x46 0x49 0x46 0x00 0x01 0x01 0x00 0x00 0x01
When I print header.marker, it shows exactly what it should (0xFFD8FFE0). But when I print header.length, it shows 0x1000 instead of 0x0010. The same thing is with xdensity and ydensity. Why do I get wrong data when reading a WORD?
You are on an x86 cpu which stores words low byte-high byte (little endian)
The binary file is presumably stored in big endian.
You need to manually swap each byte in the file (or possibly your JFIF library will do this for you)
ps. The safest way to swap bytes is to use the ntohs() and htons() macros in your 'C' library.
See the wiki article for the details of endianness
Related
I have a variable of type BYTE*, in which an address from memory is: BYTE* address = (BYTE*)0x4A4B4C4D and a BYTE Array with 5 digits, where I want to copy the address exactly as it is. BYTE* jmp = new BYTE[5] {0xE9, 0x00, 0x00, 0x00, 0x00} This array is supposed to represent a 32 bit jump and I have to copy the address to the last 4 digits because it is 4 bytes large. I’ve tried memcpy before, but it seems like memcpy is only copying the bytes that are at that address in memory and that’s what I don’t want. So my goal is to have a byte array that looks like this: BYTE[5] {0xE9, 0x4A, 0x4B, 0x4C, 0x4D}.
Edit:
BYTE* jmp = new BYTE[5] {0xE9, 0x00, 0x00, 0x00, 0x00};
BYTE* address = (BYTE*)0x4A4B4C4D;
memcpy((jmp + 1), &address, 4);
delete[] jmp;
You're very "pointer-heavy".
BYTE jmp[5] = {0xE9};
uint32_t address = 0x4A4B4C4D;
memcpy(jmp + 1, &address, 4);
or, depending on endianness,
BYTE jmp[5] = {0xE9};
uint32_t address = 0x4D4C4B4A;
memcpy(jmp + 1, &address, 4);
So there's a couple problems here.
First of all, you are missing a 4 digit in your assignment to address, this is why you get a confusing 0xE9 0x4D 0xBC 0xA4 0x04
BYTE* address = (BYTE*)0x4A4B4C4D;
^
this was missing
The reason the byte ordering is changed when you do a memcpy is because endianness, read it up:
https://en.wikipedia.org/wiki/Endianness
In your case, it's little-endian.
Memcpy will just copy the memory content as-is. If you need the jmp to order the bytes in a different way, then the only way is to manually copy each byte across:
BYTE *ptr_address = (BYTE *)&address;
for(int i=0;i<4;i++)
{
jmp[1+i] = ptr_address[3-i];
}
I'm using a Mifare 1k card and the acr1252 reader; I'm developing using visual c++ and the Winscard library.
I've successful achieved to read the single block using the following code:
// Read binary blocks
// Class: FF
// INS: B0
// P1: 00
// P2: the starting block number
// Le: length to read (multiple of 16)
BYTE ReadBinary[] = { 0xFF, 0xB0, 0x00, 0x00, 0x10 };
BYTE readRes[256] = { 0 };
DWORD lenRead = sizeof(readRes);
SCardTransmit(hCard, SCARD_PCI_T1, ReadBinary, sizeof(ReadBinary), NULL, readRes, &lenRead)
This function call returns SCARD_S_SUCCESS and readRes contains the block value + SW1 and SW2 with values 0x90 0x00 (success)
What i'm trying to do is reading 2 consecutive memory blocks (i.e. the block 0 and the block 1 of sector 0) using the same function only changing the apdu command with:
ReadBinary[] = { 0xFF, 0xB0, 0x00, 0x00, 0x20 };
// Last byte changed to read 2 blocks
But is not working: the return status still SCARD_S_SUCCESS but the data read contains only SW1 and SW2 with values 0x63 0x00 (error).
AFAIK with Mifare 1k cards is possible to read the first 3 blocks of a sector but all the reading tests that try to read more than a sector fail with that error.
Am i missing something?
I am writing a plugin for the TS3 Client, but I ran into an issue...
One of the channel names has a special sign (╠) in it, which is a special character from the extended ascii table I think.
When logging it INSIDE teamspeak, the character shows fine, but when trying to copy it to the windows clipboard using its C interface it returns a whole different character (â).
I have tried converting it to WCHAR after I read that the extended ascii table uses more bytes than the regular char, but that didn't work either.
I use the following code to copy the char* to the clipboard which I found somewhere and altered with some other code I found for using WCHAR:
void SaveClipboard(char* tx)
{
WCHAR text[140];
swprintf(text, 140, L"%hs", tx);
if(OpenClipboard(NULL))
{
EmptyClipboard();
HGLOBAL global = GlobalAlloc(GMEM_DDESHARE, 2 * (wcslen(text) + 1)); //text size + \0 character
WCHAR* pchData;
pchData = (WCHAR*)GlobalLock(global);
wcscpy(pchData, text);
GlobalUnlock(pchData);
SetClipboardData(CF_UNICODETEXT, global);
CloseClipboard();
}
}
wchar_t is UTF-16 encoded, but the data you get is UTF-8 encoded. You don't convert between these two encodings, you simply reinterpret the bytes.
Looking at the code points for those characters it should become obvious what's happening: The UTF-8 code point for ╠ is 0xE2 0x95 0xA0 and the UTF-16 code point for â is 0x00 0xE2, while the UTF-16 code point for ╠ is 0x25 0x60.
swprintf(text, 140, L"%hs", tx); <- This simply converts each char into a wchar_t, turning the 3 byte UTF-8 code point 0xE2 0x95 0xA0 into three 2 byte UTF-16 code points: 0x00 0xE2, 0x00 0x95 and 0x00 0xA0.
To get 0x25 0x60 from 0xE2 0x95 0xA0 you need to actually convert the data:
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>> converter;
std::wstring text = converter.from_bytes(tx);
Alternatively, since you are using WINAPI already, you can use MultiByteToWideChar:
WCHAR text[140];
int length = MultiByteToWideChar(CP_UTF8, 0, tx, -1, (LPWSTR)text, 140);
I have an unsigned long long variable which I want to write to a binary file. However, I need to neglect all leading bytes which are zero.
This means
unsigned long long toWrite = 4;
should write 0x04 and not 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x04 to the stream.
#include <fstream>
int main(){
std::ofstream out("test.txt", std::ios::binary);
unsigned long long toWrite = 4;
out << cutoffZeroBytes(toWrite);
out.close();
return 1;
}
I was thinking about making cutoffZeroBytes a function which returns a char*. But if there are zero bytes in the middle (e.g. 0x03 0x00 0xf1), then I think I couldn't write it to the stream, since 0x00 determines the end of an char array.
I'm a little clueless here and need some help.
One way is using write for this aim.
So, just change:
out << cutoffZeroBytes(toWrite);
to:
out.write((char*)&toWrite, sizeof(toWrite));
And if you want to cut this number:
char* start = (char*)&toWrite;
int pi = sizeof(toWrite);
for (; pi > 0; pi--, start++)
if (*start)
break;
out.write(start, pi);
I am trying to save a raw byte array into a file:
mDataStream.writeRawData( ( (const char *)&testPacket), 188);
The test packet is just an array of unsigned char, the packet is copied in the right size, but the bytes are reordered. ie: 0x47 0x00 0x10 0x20 ... becomes 0x00 0x47 ox20 0x10.
This looks like an endianness problem, but i've tried setting the byte order to little endian with unsuccessful results.