Storing BYTE* address in BYTE array - c++

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];
}

Related

C++ Pass bytes from char* to a BYTE*

I would like to know how to pass/COPY a sequence of bytes represented as a char* to a BYTE* in C++ in Windows.
Let's say I have this char* :
const char *ByteString = "\x3B\xC8\x74\x1B"
How would I COPY each byte from this char* to a BYTE *Bytes and vice-versa ?
EDIT: Thanks alot for everyone's help !
The definition of BYTE is:
typedef unsigned char BYTE;
which is not the same as a const char, so you'd need to convert it, but note that casting away const from something declared const to start with results in undefined behaviour and trying to actually change the data poses an even bigger risk.
BYTE* Bytes = reinterpret_cast<BYTE*>(const_cast<char*>(ByteString));
Edit: I just noticed that converting a const char* to a BYTE* was taken out of the question but I'll leave it here for now.
Copying the data (not as a zero terminated string) could be done like this:
const char ByteString[] = "\x3B\xC8\x74\x1B";
BYTE* Bytes = new BYTE[sizeof(ByteString)-1];
std::memcpy(Bytes, ByteString, sizeof(ByteString)-1);
// Use your Bytes
delete[] Bytes; // manual delete when you are done
Or better:
const char ByteString[] = "\x3B\xC8\x74\x1B";
std::basic_string<BYTE> Bytes( reinterpret_cast<const BYTE*>(ByteString), sizeof(ByteString)-1 );
// use Bytes
// Bytes.data() returns a BYTE*
// Bytes.size() returns the length.
But given the nature of what you are doing, you could probably skip these conversions and use an array of the correct type to start with:
BYTE Bytes[] = { 0xA1, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xC8, 0x74, 0x1B };
or
std::basic_string<BYTE> Bytes({ 0xA1, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xC8, 0x74, 0x1B });
These won't need any conversions when all you deal with is raw BYTE data. Here's an example using ReadProcessMemory and a basic_string for a buffer and pattern.
using BYTEstr = std::basic_string<BYTE>; // just for convenience
BYTEstr Buffer(1024, 0); // 1024 BYTES initialized with 0
BYTEstr Pattern({ 0xA1, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xC8, 0x74, 0x1B });
ReadProcessMemory(hProcess, lpBaseAddress, Buffer.data(), Buffer.size(), &lpNumberOfBytesRead);
BYTEstr::size_type pos = Buffer.find(Pattern);
if (pos == BYTEstr::npos) {
std::cout << "Pattern not found\n";
} else {
std::cout << "Pattern found at position " << pos << "\n";
}
To respect const, use
const BYTE *Bytes = reinterpret_cast<const BYTE*>(ByteString);
and vice versa:
const char *ByteString = reinterpret_cast<const char *>(Bytes);
If you want to make copy of the buffer so that you can modify it, use
len = LenOfChrStr;
BYTE *Bytes = new BYTE[len];
memcpy(Bytes, ByteStr, len);
Given a char const * array of characters, we can make a new buffer with readwrite BYTEs for the API to possibly edit:
char const *ByteString = "\x3B\xC8\x74\x1B";
auto len = std::strlen(ByteString) + 1;
auto ptr = std::make_unique<BYTE[]>(len);
std::memcpy(ptr.get(), ByteString, len);
If you need to surrender the ownership of the memory to the function:
Func(ptr.release());
But if you want to keep the ownership yourself:
Func(ptr.get());
In MSVC (I guess this is your compiler for WinAPI application) you can make the char type unsigned with /J option (more here: https://learn.microsoft.com/en-us/cpp/build/reference/j-default-char-type-is-unsigned?view=vs-2017). If you do this, BYTE becomes the same as char and no conversion would be necessary.
Please note, this might have some other side effects in your application.

Encrypt in C++ / Decrypt in x86

I am having a problem with a school assignment. The assignment is to write a metamorphic Hello World program. This program will produce 10 .com files that print "Hello World!" when executed. Each of the 10 .com files must be different from the others. I understand the concept of metamorphic vs oligomorphic vs polymorphic. My program currently creates 10 .com files and then writes the machine code to the files. I began by simply writing only the machine code to print hello world and tested it. It worked just fine. I then tried to add a decryption routine to the beginning of the machine code. Here is my current byte array:
#define ARRAY_SIZE(array) (sizeof((array))/sizeof((array[0])))
BYTE pushCS = 0x0E;
BYTE popDS = 0x1F;
BYTE movDX = 0xBA;
BYTE helloAddr1 = 0x1A;
BYTE helloAddr2 = 0x01;
BYTE movAH = 0xB4;
BYTE nine = 0x09;
BYTE Int = 0xCD;
BYTE tOne = 0x21;
BYTE movAX = 0xB8;
BYTE ret1 = 0x01;
BYTE ret2 = 0x4C;
BYTE movBL = 0xB3;
BYTE keyVal = 0x03; // Encrypt/Decrypt key
typedef unsigned char BYTE;
BYTE data[] = { 0x8D, 0x0E, 0x01, 0xB7, 0x1D, 0xB3, keyVal, 0x30, 0x1C, 0x46, 0xFE, 0xCF, 0x75, 0xF9,
movDX, helloAddr1, helloAddr2, movAH, nine, Int, tOne, movAX, ret1, ret2, Int, tOne,
0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x0D, 0x0D, 0x0A, 0x24 };
The decryption portion of the machine code is the first 14 bytes of "data". This decryption routine would take the obfuscated machine code bytes and decrypt them by xor-ing the bytes with the same key that was used to encrypt them. I am encrypting the bytes in my C++ code with this:
for (int i = 15; i < ARRAY_SIZE(data); i++)
{
data[i] ^= keyVal;
}
I have verified over and over again that my addressing is correct considering that the code begins at offset 100. What I have noticed is that when keyVal is 0x00, my code runs fine and I get 10 .com files that print Hello World!. However, this does me no good as 0x00 leaves everything unchanged. When I provide an actual key like 0x02, my program no longer works. It simply hangs until I close out DosBox. Any hints as to the cause of this would be a great help. I have some interesting plans for junk insertion (The actual metamorphic part) but I don't want to move on to that until I figure out this encrypt/decrypt issue.
The decryption portion of the machine code is the first 14 bytes of "data".
and
for (int i = 15; i < ARRAY_SIZE(data); i++)
do not match since in C++ array indexes start at 0.
In your array data[15] == helloAddr1 which means you are not encrypting the data[14] == movDX element. Double-check which elements should be encrypted and start at i = 14 if required.

Memset an address into four bytes of allocated memory

EDIT: Thanks to Ipmcc, he has given me a solution in the comments.
I would like to use memset to allocate a four-byte address into the first four bytes of memory that I have dynamically allocated. An example with comments of what I'd like to do is shown below. All of my attempts to find out how to do this or figure it out myself has ended up without success.
Any help would be most appreciated, thank you.
int main(void)
{
// Define and assign eight bytes of memory
unsigned char *data1 = new unsigned char [8];
unsigned char *data2 = new unsigned char [8];
// Set all eight bytes in both data1 and data2 to 0x00
memset(data1, 0x00, 8);
memset(data2, 0x00, 8);
// Lets say that the address of *data1 is: 00508d30
// Lets say that the address of *data2 is: 0050b180
// I want to set the first four bytes in data1 to the
// address of data2, so it would look something like this...
memset(data1, 0x00, 1); ++data1;
memset(data1, 0x50, 1); ++data1;
memset(data1, 0xB1, 1); ++data1;
memset(data1, 0x80, 1);
data1 -= 3; // Reset pointer
// But of course this is in no way practical or viable
// since the addresses change each time (also it's not a good
// practice to hard-code things in anyway). So I'm wondering
// if there's a proper/feasible way to do this.
return 0;
}

Remove null byte every X byte c++ WINAPI

I have a buffer type like this:
unsigned char buffer[] = {
0xB8, 0xB8, 0x00, 0xB8, 0xB8, 0x00, 0xB8, 0xB8, 0x00, 0xB8, 0xB8, 0x00,..
};
So I need to remove the null byte every X (every 2 bytes in this example). I don't want to remove all null byte because in my buffer I have melt bytes.
So just need to remove a range and in WinAPI. How can I do that?
I'm still not very comfortable with C++, also the buffer can be big.
I think the right way is by copy the buffer by memcpy in a loop but I can't find the syntax.
It seems that you don't want to use any of the more powerful features of C++ so I suspect that you are really looking for a C style routine. That would look like this:
void copyskip(void *dest, const void *src, size_t srclen, size_t skip)
{
size_t destidx = 0;
for (size_t srcidx=0; srcidx<srclen; )
{
if ((srcidx+1) % skip != 0)
{
((char*)dest)[destidx] = ((char*)src)[srcidx];
destidx++;
}
srcidx++;
}
}
You'd need to allocate the destination buffer before calling. And for your example you would pass 3 for the skip parameter.
Personally I'd much rather do it using C++ standard containers, but this is what I think you asked for.

Bit fields and endianness

I have defined the following struct to represent an IPv4 header (up until the options field):
struct IPv4Header
{
// First row in diagram
u_int32 Version:4;
u_int32 InternetHeaderLength:4; // Header length is expressed in units of 32 bits.
u_int32 TypeOfService:8;
u_int32 TotalLength:16;
// Second row in diagram
u_int32 Identification:16;
u_int32 Flags:3;
u_int32 FragmentOffset:13;
// Third row in diagram
u_int32 TTL:8;
u_int32 Protocol:8;
u_int32 HeaderChecksum:16;
// Fourth row in diagram
u_int32 SourceAddress:32;
// Fifth row in diagram
u_int32 DestinationAddress:32;
};
I now also captured an IP frame with Wireshark. As an array literal it looks like this:
// Captured with Wireshark
const u_int8 cIPHeaderSample[] = {
0x45, 0x00, 0x05, 0x17,
0xA7, 0xE0, 0x40, 0x00,
0x2E, 0x06, 0x1B, 0xEA,
0x51, 0x58, 0x25, 0x02,
0x0A, 0x04, 0x03, 0xB9
};
My question is: How can I create a IPv4Header object using the array data?
This doesn't work because of incompatible endianness:
IPv4Header header = *((IPv4Header*)cIPHeaderSample);
I'm aware of the functions like ntohs and ntohl, but it can't figure out how to use them correctly:
u_int8 version = ntohs(cIPHeaderSample[0]);
printf("version: %x \n", version);
// Output is:
// version: 0
Can anyone help?
The most portable way to do it is one field at a time, using memcpy() for types longer than a byte. You don't need to worry about endianness for byte-length fields:
uint16_t temp_u16;
uint32_t temp_u32;
struct IPv4Header header;
header.Version = cIPHeaderSample[0] >> 4;
header.InternetHeaderLength = cIPHeaderSample[0] & 0x0f;
header.TypeOfServer = cIPHeaderSample[1];
memcpy(&temp_u16, &cIPHeaderSample[2], 2);
header.TotalLength = ntohs(temp_u16);
memcpy(&temp_u16, &cIPHeaderSample[4], 2);
header.Identification = ntohs(temp_u16);
header.Flags = cIPHeaderSample[6] >> 5;
memcpy(&temp_u16, &cIPHeaderSample[6], 2);
header.FragmentOffset = ntohs(temp_u16) & 0x1fff;
header.TTL = cIPHeaderSample[8];
header.Protocol = cIPHeaderSample[9];
memcpy(&temp_u16, &cIPHeaderSample[10], 2);
header.HeaderChecksum = ntohs(temp_u16);
memcpy(&temp_u32, &cIPHeaderSample[12], 4);
header.SourceAddress = ntohl(temp_u32);
memcpy(&temp_u32, &cIPHeaderSample[16], 4);
header.DestinationAddress = ntohl(temp_u32);
ntohl and ntohs don't operate on 1-byte fields. They are for 32 and 16 bit fields, respectively. You probably want to start with a cast or memcpy then byte swap the 16 and 32-bit fields if you need to. If you find that version isn't coming through with that approach without any byte swapping, then you have bit field troubles.
Bit fields are a big mess in C. Most people (including me) will advise you to avoid them.
You want to take a look at an the source for ip.h, that one is from FreeBSD. There should be a pre-dedined iphdr struct on your system, use that. Don't reinvent the wheel if you don't have to.
The easiest way to make this work is to take a pointer to the byte array from wireshark and cast it into a pointer to an iphdr. That'll let you use the correct header struct.
struct iphdr* hrd;
hdr = (iphdr*) cIPHeaderSample;
unsigned int version = hdr->version;
Also, htons takes in a 16-bit and changes the byte order, calling it on a 32-bit variable is just going to make a mess of things. You want htonl for 32-bit variables. Also note that for a byte there is no such thing as an endianess, it takes multiple bytes to have different endianess.
Updated:
I suggest you use memcpy to avoid the issues of bitfields and struct alignment, as this can get messy. The solution below works on a simple example, and can be easily extended:
struct IPv4Header
{
uint32_t Source;
};
int main(int argc, char **argv) {
const uint8_t cIPHeaderSample[] = {
0x45, 0x00, 0x05, 0x17
};
IPv4Header header;
memcpy(&header.Source, cIPHeaderSample, sizeof(uint8_t) * 4);
header.Source= ntohl(header.Source);
cout << hex << header.Source<< endl;
}
Output:
45000517