Buffer overflow: execute char array loaded into memory - c

I'm an ethical hacking student and have been given this as an exercise. I've been stuck on it for two days now.
We're writing a program that is purposely vulnerable to a "buffer overflow".
#include <stdio.h>
void badf(int n, char c, char* buffer)
{
char mycode[] = {
0xeb, 0x0f, 0xb8, 0x0b,
0x00, 0x00, 0x00, 0x8b,
0x1c, 0x24, 0x8d, 0x0c,
0x24, 0x31, 0xd2, 0xcd,
0x80, 0xe8, 0xec, 0xff,
0xff, 0xff, 0x2f, 0x62,
0x69, 0x6e, 0x2f, 0x6c,
0x73, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00
}; // 37 bytes
int i;
// Copy mycode array into buffer array
for (i=0; i<n; i++)
{
buffer[i]=mycode[i];
}
// Overwrite Base Pointer
buffer[37] = 0x00;
buffer[38] = 0x00;
buffer[39] = 0x00;
buffer[40] = 0x00;
// Overwrite Instruction Pointer
buffer[41] = 0x90;
buffer[42] = 0x83;
buffer[43] = 0x04;
buffer[44] = 0x08;
}
void f(int n, char c)
{
char buffer[37];
badf(n,c,buffer);
}
void test()
{
printf("test\n");
}
int main()
{
f(37,0x00);
return 0;
}
The mycode array contains "malicious" machine code (it actually just calls execv with /bin/ls). badf is the "vulnerable" function. At the moment you can see I'm overwriting the Base Pointer with 0x00s and the Instuction Pointer with 0x08048390 which is the address of the test() function. This works, 'test' is printed to the terminal.
Now my next exercise is to "use ddd to find the address of your code array and modify the C to write this address over the instruction pointer, as you did in the previous step".
What I don't understand, is how I can use ddd to find the address of my code array. I can easily find the address where the array is moved to BP:
0x08048260 <badf+12>: movb $0xeb,-0x29(%ebp)
0x08048264 <badf+16>: movb $0xf,-0x28(%ebp)
0x08048268 <badf+20>: movb $0xb8,-0x27(%ebp)
.....
Or where it is copied into the buffer array:
0x080482f4 <badf+160>: movl $0x0,-0x4(%ebp)
0x080482fb <badf+167>: jmp 0x8048316 <badf+194>
0x080482fd <badf+169>: mov -0x4(%ebp),%edx
0x08048300 <badf+172>: mov 0x10(%ebp),%eax
.....
But of course this is not what we're looking for.
How can I find the Instruction Pointer address to execute machine code that has been loaded in by writing it in the buffer array this way?
edit: ddd is the debugger we're using, also note we're working with a 32bit linux. The code is compiled with -fno-stack-operator flag, disabling the compilers auto-checks for buffer overflows.

Since you copy myCode into the buffer, you could simply use buffer itself:
Assuming a little-endian machine:
// Overwrite Instruction Pointer
buffer[41] = (char)(((uintptr_t)buffer) >> 0);
buffer[42] = (char)(((uintptr_t)buffer) >> 8);
buffer[43] = (char)(((uintptr_t)buffer) >> 16);
buffer[44] = (char)(((uintptr_t)buffer) >> 24);

I don't know how to do it with ddd, but you could modify badf to print mycode address by using a print statement like this:
printf("mycode address: %p", (void *) mycode);
See what that prints, and just write that to instruction pointer

Related

Defining array of bytes for use to call later in C program

Initializing a SI labs radio, the software develops a header file as well as a patch file. first part is, depending on the patch file it outputs different ways. here is a snippet of each patch:
Rev B patch:
#define SI446X_PATCH_CMDS \
{ 0x04,0x11,0xF7,0x76,0x00,0x00,0xA6,0x82 }, \
{ 0x05,0x61,0xE6,0x82,0x5E,0xB7,0xFB,0x93 }, \
{ 0x05,0x1E,0x12,0xBD,0x5A,0xC2,0x52,0x41 }, \
{ 0xE7,0xF4,0xDF,0x6A,0x24,0xD9,0xBA,0x31 }, \
OR
Rev C patch:
#define SI446X_PATCH_CMDS \
0x08,0x04,0x21,0x71,0x4B,0x00,0x00,0xDC,0x95, \
0x08,0x05,0xA6,0x22,0x21,0xF0,0x41,0x5B,0x26, \
0x08,0xE2,0x2F,0x1C,0xBB,0x0A,0xA8,0x94,0x28, \
0x08,0x05,0x87,0x67,0xE2,0x58,0x1A,0x07,0x5B, \
Now this will be hardcoded into the software and either one commented out. but it must have been done this way for a reason and i dont understand it. for initial testing i placed each line of 8 bytes (as it needs to be pushed over SPI this way) into an array and then created a pointer to the array since the length isnt necessary as they are all 8 bytes like i said. iss there a more intelligent way i should cade this based on the way it is presented?
uint8_t array_1[8] = { 0x04, 0x11, 0xF7, 0x76, 0x00, 0x00, 0xA6, 0x82 };
uint8_t array_2[8] = { 0x05, 0x61, 0xE6, 0x82, 0x5E, 0xB7, 0xFB, 0x93 };
uint8_t *theArrays[] = { array_1, array_2, array_3, array_4, array_5, array_6,
array_7, array_8, array_9, array_10, array_11, array_12, array_13,
I then program the SPI using this code and manually typed in the qty into a for loop as i cant get sizeof from the pointer array.
HAL_SPI_Transmit(&hspi1, theArrays[i], 8, 50);
These macros just make things a bit easier.
Assuming the number of (sub)arrays in both macros matches the number of arrays in your array of pointers, your code would look like this in full version:
uint8_t array_1[8] = { 0x04, 0x11, 0xF7, 0x76, 0x00, 0x00, 0xA6, 0x82 };
uint8_t array_2[8] = { 0x05, 0x61, 0xE6, 0x82, 0x5E, 0xB7, 0xFB, 0x93 };
uint8_t array_3[8] = ...
uint8_t array_4[8] = ...
uint8_t array_...
uint8_t array_12[8] = ...
uint8_t array_13[8] = ...
uint8_t *theArrays[] = { array_1, array_2, array_3, array_4, array_5, array_6,
array_7, array_8, array_9, array_10, array_11, array_12, array_13,
...
HAL_SPI_Transmit(&hspi1, theArrays[i], 8, 50);
With these macros (stored in some nice header) you can just do this:
Revision B:
#define SPI_MESSAGE_SIZE 8
const uint8_t theArray[][SPI_MESSAGE_SIZE] = {SI446X_PATCH_CMDS};
_Static_assert(sizeof theArray/sizeof *theArray == SOME_EXPECTED_SIZE, "SI446X_PATCH_CMDS corrupt");
...
HAL_SPI_Transmit(&hspi1, theArrays[i], SPI_MESSAGE_SIZE, 50);
or in case of Revision C
#define SPI_MESSAGE_SIZE 8
const uint8_t theArray[] = {SI446X_PATCH_CMDS};
_Static_assert(sizeof theArray/sizeof *theArray == SOME_EXPECTED_SIZE, "SI446X_PATCH_CMDS corrupt");
...
// For Rev C, the array contains a <length> byte before the SPI data.
// Adjust addressing accordingly
uint8_t len = theArrays[i*(SPI_MESSAGE_SIZE+1)];
HAL_SPI_Transmit(&hspi1, &theArrays[i*(SPI_MESSAGE_SIZE+1)+1], len, 50);
The static assert was suggested by Lundin. I am not aware of the correct value to compare but there should be some useful define somewhere in Silabs Radio's headers.

Shellcode crashing target PE

I am currently attempting to patch a target x86 PE file from the disk with a tool, patch.exe.
purpose
The purpose of this tool will be to eventually write/insert a multi-function payload into the target executable, who's purpose is to track the position of certain frames inside a game which I created.
background
I am doing this by mapping the file into memory with PAGE_READWRITE protection flag. After locating the RVA of foobar(...) function from memory, I am replacing the call to this function with a JMP (0xE9) instruction followed by the RVA of the payload shellcode (which is previously appended to a new section I have created within the target PE file beforehand).
When the shellcode simply contains the following bytes
unsigned char shellcode[16] = {0x33, 0xc0, 0xc3, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc}
which translates to the following C function
unsigned long basic_ret() { return 0; }
the target executable successfully executes
problem
however, if I try to include another function (0xDEADBEEF) within the code
unsigned char shellcode[32] =
{
0x6a, 0x0b, 0x68, 0x9c, 0xc2, 0xf4, 0x00, 0x6a, 0x0a, 0x68, 0xa8, 0xc2, 0xf4, 0x00, 0x68, 0xb4,
0xc2, 0xf4, 0x00, 0xb8, 0xef, 0xeb, 0xda, 0xed, 0xff, 0xd0, 0x83, 0xc4, 0x14, 0xc3, 0xcc, 0xcc
};
which translates to the following C function (a simple JMP taking 3 arguments on the stack, to another function)
int simple_jmp()
{
typedef int (*_jmp_target)(void*, int, void*);
_jmp_target jmp_target = (_jmp_target) 0xDEADBEEF;
return jmp_target (0, 5, 0);
}
where jmp_target is filled by patch.exe with the RVA to a function previously referred to, which was inserted into the new section of the target PE.
When the the target executable is executed, this time, it reaches some type of violation/crash (confirmed by the presence of WerFault.exe alongside its execution).
What is the reason for this problem, what am I missing?
diagnostics
When I observe the patched bytes in memory (of the mapped PE file), I can see that 0xdeadbeef is replaced by 0x0dc3f4de which is the same address from which the inserted function shellcode starts. At this point, I assumed there would be no crash, little to my surprise - crash!

Powershell: how to intialize an array of bytes like in C?

In C you can do something like:
uint16_t datalen = 1024;
uint16_t crc = 0x1021;
uint8_t myHeader = {0x41, 0xBE, 0x21, 0x08, datlen/256, datalen%256, crc/256, crc%256};
Now, how can I accomplish an array initialization like this in Powershell?
I want to send the byte array later to serial port.
Not so different:
[uint16]$datalen = 1024
[uint16]$crc = 0x1021
[byte[]]$myHeader = 0x41, 0xBE, 0x21, 0x08, ($datalen/256), ($datalen%256), ($crc/256), ($crc%256)

why does this make my display go mad? (but only sometimes)

it seems this code make my display go crazy sometimes (but only sometimes). But when I remove dat=~dat; it seems to work fine.
why?
what I am trying to do here is just make the ascii letters be the oposite: so for example:
11001000 will be:
00110111
or
10101111 would be:
01010000
the reason for doing this is that i want to have one row (the active row) in the diplay window with black on white pixels instead of opostie like the rest of the display window.
Is there some other way I could do this? (invert the numbers)
FYI: I am programing in C. Atmel studio. atmega 4809, SSD1305z display, SPI-simular interface.
void displayinvertedString(char str[], uint8_t ypos,uint8_t xpos)
{
Set_Page_Address(ypos);
Set_Column_Address(xpos);
int len = strlen(str);
uint8_t dat;
int temp;
for (int e=0; e<len; e++)
{
dat = 0xff;
Write_Data(dat); //to get an extra space between the
// numbers/letters for
//making it easier to read the text on the display
temp = str[e];
temp=temp-0x20; // As the lookup table starts from Space(0x20)
for (int w=0; w<5; w++)
{
dat= OledFontTable[temp][w]; // Get the data to be displayed for LookUptable
dat =~ dat;
Write_Data(dat);
}
}
}
----------
static uint8_t OledFontTable[][FONT_SIZE]={
//static uint8_t OledFontTable[] = {
0x00, 0x00, 0x00, 0x00, 0x00, // space
0x00, 0x00, 0x2f, 0x00, 0x00, // !
0x00, 0x07, 0x00, 0x07, 0x00, // "
0x14, 0x7f, 0x14, 0x7f, 0x14, // #
0x24, 0x2a, 0x7f, 0x2a, 0x12, // $
0x23, 0x13, 0x08, 0x64, 0x62, // %
0x36, 0x49, 0x55, 0x22, 0x50, // &
ETC. Etc.
just more raw pixel data here. this part ends like this:
0x00, 0x00, 0xFF, 0x00, 0x00, // |
0x00, 0x82, 0x7C, 0x10, 0x00, // }
0x00, 0x06, 0x09, 0x09, 0x06 // ~ (Degrees)
};
void Write_Data(unsigned char Data)
{
PORTA.OUTCLR = PIN7_bm; //cs
PORTB.OUTSET = PIN2_bm; //dc
Write_Command(Data); //
}
void Write_Command(unsigned char data)
{
SPI0.DATA = data; // copy data to DATA register
while ((SPI0.INTFLAGS & SPI_RXCIF_bm) == 0) ; //wait
}
I have asked a bit about this before. but i thought i would look "cleaner" with a new tread since info was missing from the last one.
It turned out I needed to toggle the chip select (CS) so the clock did not get out of sync with time.
The clock sync drifted with time.
It was going crazy faster for the non inverted data for some reason. But with the normal data it happend after some time also.
Thank you for the answers.

How to properly save and restore thread context on 64 bit process (Windows)?

I've got this code below for releasing library from some 64 bit process. It does its job, but the problem is that after restoring saved context, the target process just crashes. Dunno what is the issue here. It should set all registers and flags for what they were before, right?. What am I doin' wrong?
#ifdef _WIN64
const static unsigned char FreeLibrary_InjectionCodeRAW_x64[] =
{
0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //mov rax, value
0x48, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //mov rcx, value
0xFF, 0xD0, //call rax (FreeLibrary)
0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //mov rax, value
0xC7, 0x00, 0x01, 0x00, 0x00, 0x00, //mov [rax],1
0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //mov rax, value
0xB9, 0x64, 0x00, 0x00, 0x00, //mov ecx, 0x64
0xFF, 0xD0, //call Sleep
0xEB, 0xED, //jmp
0x00, 0x00, 0x00, 0x00 //status
};
#pragma pack(push, 1)
struct FreeLibrary_InjectionCode_x64
{
FreeLibrary_InjectionCode_x64()
{
memcpy(this, FreeLibrary_InjectionCodeRAW_x64, sizeof(FreeLibrary_InjectionCodeRAW_x64));
}
char code_1[2];
FARPROC lpFreeLibrary;
char code_2[2];
HMODULE hLib;
char code_3[4];
LPVOID lpStatusAddress;
char code_4[8];
FARPROC lpSleep;
char code_5[9];
int status;
};
#pragma pack(pop)
#endif
void FreeLib(const char what[], const char where[])
{
HANDLE hToken;
OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken);
SetPrivilege(hToken, SE_DEBUG_NAME, TRUE);
CloseHandle(hToken);
OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &hToken);
SetPrivilege(hToken, SE_DEBUG_NAME, TRUE);
CloseHandle(hToken);
HMODULE hMod;
DWORD dwProcessId = GetProcessIdByName(where);
if ((hMod = GetModuleHandleInProcess(what, dwProcessId)) != NULL)
{
HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | SYNCHRONIZE, FALSE, dwProcessId);
if (hProcess != NULL)
{
HMODULE hKernel = LoadLibrary("kernel32.dll");
FARPROC FLaddr = GetProcAddress(hKernel, "FreeLibrary");
FARPROC Saddr = GetProcAddress(hKernel, "Sleep");
HANDLE hThread = OpenThread(THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_QUERY_INFORMATION | THREAD_SET_INFORMATION | THREAD_SUSPEND_RESUME,
FALSE, GetValidThreadIdInProcess(dwProcessId));
if (hThread != NULL && FLaddr != NULL && Saddr != NULL)
{
LPVOID addr = VirtualAllocEx(hProcess, NULL, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
LPVOID lpStatusAddress = (PUCHAR)addr + (sizeof(FreeLibrary_InjectionCode_x64)-sizeof(int));
FreeLibrary_InjectionCode_x64 code = FreeLibrary_InjectionCode_x64();
code.hLib = hMod;
code.lpFreeLibrary = FLaddr;
code.lpSleep = Saddr;
code.lpStatusAddress = lpStatusAddress;
WriteProcessMemory(hProcess, addr, &code, sizeof(FreeLibrary_InjectionCode_x64), NULL);
CONTEXT ctx, oldCtx;
ctx.ContextFlags = CONTEXT_ALL;
SuspendThread(hThread);
GetThreadContext(hThread, &ctx);
memcpy(&oldCtx, &ctx, sizeof(CONTEXT));
ctx.Rip = (DWORD64)addr;
SetThreadContext(hThread, &ctx);
ResumeThread(hThread);
while (!code.status)
{
Sleep(15);
ReadProcessMemory(hProcess, addr, &code, sizeof(FreeLibrary_InjectionCode_x64), NULL);
}
SuspendThread(hThread);
SetThreadContext(hThread, &oldCtx);
ResumeThread(hThread);
VirtualFreeEx(hProcess, addr, 4096, MEM_DECOMMIT);
CloseHandle(hThread);
}
CloseHandle(hProcess);
}
}
}
Windows 64-bit uses the fastcall calling convention. In this convention the caller of a function is responsible for reserving 4 * 64 bit (32 byte) on the stack for the called function to save registers.
This means your calls should look like this:
sub rsp, 32
call rax
add rsp, 32
In your code your calls to FreeLibrary or Sleep overwrite stack that doesn't belong to their stack frame, causing a crash later on.
You are not doing any error handling to make sure the memory was actually allocated and written to the other process before executing it, or to make sure that ReadProcessMemory() succeeded, or to make sure that the thread suspend/resume and context swapping was successful.
Chances are, the remote thread is likely done running your injected code and tries to run its original code (or even random code that happens to follow your allocated block in memory) before your injector has a chance to swap back in the original context information. That might account for the crashing.
Instead of hijacking an existing thread in the other process and swapping out its context behind its back, you might want to consider using CreateRemoteThread() instead to run your injected code in its own dedicated thread. No context swapping needed.

Resources