Buffer overflow successful, but it shouldn't be? - gdb

This is my program, with a vulnerable char buffer, name[400].
void greeting(char *temp1,char *temp2)
{
char name[400];
strcpy(name,temp2);
printf("Hello %s %s\n", temp1, name);
}
int main(int argc,char *argv[])
{
greeting(argv[1],argv[2]);
return 0;
}
Compiled as follows on Linux (64-bit) with ASLR disabled:
gcc -m32 -ggdb -fno-stack-protector -mpreferred-stack-boundary=2 -z execstack -o buffer buffer.c
(gdb) run Mr `perl -e 'print "A" x 400'`
Hello Mr AAAAAAA.... (truncated)
Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb) info reg eip ebp
eip 0x41414141
ebp 0x41414141
I'm assuming here that a null byte is added, resulting in the overflow, but what I don't understand is how the EIP can be 0x41414141 with only a 1 byte overflow?
EDIT: After more probing with gdb, there is no null byte added, and there is no overflow at all when only 400 bytes are entered. So how does my EIP end up pointing to my buffer contents without any overflow? I'm assuming that the absense of a null byte causes problems for printf().

C string are NUL terminated, so you end up with a 1-byte overflow with a value of zero (NUL).
The one-byte NUL overflow modifies the saved value of $ebp to point lower on the stack than it should. This results in restoring an incorrect value into $esp, and control of $eip.
Take specific note of the value of ebp. After the call, the value of $ebp is still the same, but the value it points to (the value which main will restore off the stack) has been adjusted, and points into the middle of our controlled buffer.
When greeting returns into main, nothing happens. However, when main restores the stack frame with a leave instruction, the stack pointer $esp is set into the middle of our controlled buffer. When the ret instruction is executed, we have control over $eip.
Note that I've used a cyclic pattern generated by pwntools rather than the standard AAAAA since we can use it to calculate offsets. For example 'aaaa' => 0, 'aaab' => 1, 'aaba' => 2.
Before Strcpy
EBP: 0xffffc6e8 --> 0xffffc6f8 --> 0x0
ESP: 0xffffc54c --> 0xffffc558 --> 0xffffc5c8 --> 0xf63d4e2e
EIP: 0x8048466 (<greeting+25>: call 0x8048320 <strcpy#plt>)
After Strcpy
EBP: 0xffffc6e8 --> 0xffffc600 ("raabsaabtaabuaabvaabwaabxaabyaab"...)
ESP: 0xffffc54c --> 0xffffc558 ("aaaabaaacaaadaaaeaaafaaagaaahaaa"...)
EIP: 0x804846b (<greeting+30>: lea eax,[ebp-0x190])
Before leave in main
EBP: 0xffffc600 ("raabsaabtaabuaabvaabwaabxaabyaab"...)
ESP: 0xffffc6f0 --> 0xffffc9bb ("Mister")
EIP: 0x80484b1 (<main+39>: leave)
After leave in main
EBP: 0x62616172 (b'raab')
ESP: 0xffffc604 ("saabtaabuaabvaabwaabxaabyaabzaac"...)
EIP: 0x80484b2 (<main+40>: ret)
At ret in main
EBP: 0x62616172 (b'raab')
ESP: 0xffffc608 ("taabuaabvaabwaabxaabyaabzaacbaac"...)
EIP: 0x62616173 (b'saab')

Related

Print assembly variable C++

Hello All!
I'm doing a MASM course and I got into this exercise.
I have this simple assembly code:
.386
.model flat,c
.data
quote byte "Machines do feel", 0
message byte SIZEOF quote DUP(0),0
.code
start proc
mov esi,0
mov ecx,SIZEOF quote
LP:
mov al,quote[esi]
mov message[esi],al
inc esi
loop LP
ret
start endp
end
And I want to write a C++ program that can "printf" the variable "message".
How can I do this?
I tryed to add:
mov eax, DWORD ptr [message]
To the ".asm" file to store the address of the message variable on the register returned by the function and then I wrote this program to try to printf the values:
#include <iostream>
extern "C" char *start();
int main(){
char *message = start();
for(int i = 0x0; i < sizeof(message)/sizeof(char); i++){
printf("%s", message[i]);
}
return 0x0;
}
But when I try to run it I get the error:
Unhandled page fault on read access to 6863614D at address 0040162E (thread 0024), starting debugger...
0024:err:seh:start_debugger Couldn't start debugger L"winedbg --auto 32 68" (2)
Can you please explain me how can I print the values of the ".asm" file "message" variable?
And can also show me different methods to do this?
Thank you so much, have a nice coding!

PIN get assembly opcodes from instruction address

I am using PIN to analyze a C program's instructions and perform necessary operations. I have compiled my C program using GCC on Ubuntu and then passed the generated executable as input to the pintool. I have a pintool which calls an instruction instrumentation routine and then calls an analysis routine everytime. This is my Pintool in C++ -
#include "pin.H"
#include <fstream>
#include <cstdint>
UINT64 icount = 0;
using namespace std;
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool", "o", "test.out","A pin tool");
FILE * trace;
//====================================================================
// Analysis Routines
//====================================================================
VOID dump(VOID *ip, UINT32 size) {
unsigned int i;
UINT8 opcodeBytes[15];
UINT32 fetched = PIN_SafeCopy(&opcodeBytes[0], ip, size);
if (fetched != size) {
fprintf(trace, "*** error fetching instruction at address 0x%lx",(unsigned long)ip);
return;
}
fprintf(trace, "\n");
fprintf(trace, "\n%d\n",size);
for (i=0; i<size; i++)
fprintf(trace, " %02x", opcodeBytes[i]); //print the opcode bytes
fflush(trace);
}
//====================================================================
// Instrumentation Routines
//====================================================================
VOID Instruction(INS ins, void *v) {
INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)dump, IARG_INST_PTR, IARG_UINT32, INS_Size(ins) , IARG_END);
}
VOID Fini(INT32 code, VOID *v) {
printf("count = %ld\n",(long)icount);
}
INT32 Usage(VOID) {
PIN_ERROR("This Pintool failed\n"
+ KNOB_BASE::StringKnobSummary() + "\n");
return -1;
}
int main(int argc, char *argv[])
{
trace = fopen("test.out", "w");
if (PIN_Init(argc, argv)) return Usage();
PIN_InitSymbols();
PIN_AddInternalExceptionHandler(ExceptionHandler,NULL);
INS_AddInstrumentFunction(Instruction, 0);
PIN_AddFiniFunction(Fini, 0);
// Never returns
PIN_StartProgram();
return 0;
}
When I check my output trace I see that I get an output like this-
3
48 89 e7
5
e8 78 0d 00 00
1
55
The first row is the size in bytes of the instruction and the second row is the opcode stored in each byte.
I saw this particular forum-
https://groups.yahoo.com/neo/groups/pinheads/conversations/topics/4405#
where they mentioned that the Linux output is inconsistent and is due to a 32 bit disassembler for 64 bit instructions. I am getting the same output as the Linux ones mentioned here, while the Windows ones are the correct x86_64 opcodes I am expecting.
Any idea how I can get the correct opcodes and if I am doing the dissassembly wrong, how I can correct it. I am using a 64-bit PC so don't know if I am doing 32-bit disassembly.
In 32-bit mode, 48 is a 1 byte inc or dec (I forget which).
In 64-bit mode, it's a REX prefix (with W=1, other bits unset, selecting 64-bit operand-size). (AMD 64 repurposed the whole 0x40-f range of inc/dec short encodings as REX prefixes.)
Decoding 48 89 e7 as a 3-byte instruction instead of a 48 and 89 e7 is absolute proof that it's disassembling in 64-bit mode.
So how am I supposed to interpret the instruction here?
As x86-64 instructions, obviously.
For your case, I fed those hex bytes to a disassembler:
db 0x48, 0x89, 0xe7
db 0xe8, 0x78, 0x0d, 0x00, 0x00
db 0x55
nasm -f elf64 foo.asm && objdump -drwC -Mintel foo.o
400080: 48 89 e7 mov rdi,rsp
400083: e8 78 0d 00 00 call rel32
400088: 55 push rbp
objdump -d finds the same instruction breaks, because PIN was decoding it correctly.
The push is presumably at the start of the called function. Sticking them together sort of flattens the trace, and isn't a way to make a runnable version, just to get the bytes disassembled.
I should simple ignore the first byte and then use the remaining?
No, of course not. REX prefixes are part of the instruction. Without the 0x48, the first instruction would decode as mov edi,esp, which is a different instruction.
Try looking at some disassembly output for some existing code to get used to what x86-64 instructions look like. For specific encoding details, see Intel's vol.2 manual. It has some intro and appendix sections about instruction-encoding details. (The main body of the manual is the instruction-set reference, with the details of how every instruction works and its opcodes.) See https://software.intel.com/en-us/articles/intel-sdm#three-volume, and other links in the x86 tag wiki.
Pin has an API for disassembly, you should use it. See this question as to how it should be done:
https://reverseengineering.stackexchange.com/questions/12404/intel-pin-how-to-access-the-ins-object-from-inside-an-analysis-function

What's the significance of the App Verifier error pattern `fafa`?

My program is crashing in app verifier and I don't fully understand the crash. I have a buffer which is dynamically allocated thus from the number of bytes in a file:
DWORD dwSizeBytes = (DWORD)liSize.QuadPart+2;
TCHAR* JSONBufferW = new TCHAR [dwSizeBytes/sizeof(TCHAR)];
memset(JSONBufferW, 0, dwSizeBytes);
Where dwSizeBytes (I can see this in the crash dump) is 38. After this I read some data from a file:
if(!ReadFile(hFile, JSONBufferW, dwSizeBytes, &dwSizeBytes, NULL))
{
status = GetLastError();
TRACE_ERROR(g_hTrace, "ReadFile() failed for %S, error code=%d", strCompletePath, status);
}
This assigns 36 to dwSizeBytes leaving the last two bytes in the buffer NULL so that the buffer is NULL terminated. However under app verifier this later causes a crash when I attempt to construct a std::wstring from the buffer.
When I look at the buffer's allocation block in windbg I see that it looks like this:
0:022> dd 0x00000000`07560fd0-0x48 0x00000000`07560fd0
00000000`07560f88 00001000 00000000 abcdbbbb 00000000
00000000`07560f98 07191000 00000000 00000026 00000000
00000000`07560fa8 00001000 00000000 00000000 00000000
00000000`07560fb8 00000000 00000000 0025a230 00000000
00000000`07560fc8 00001000 dcbabbbb 0022007b
Note the 0x26 which shows my buffer is supposed to be 38 in size. Now I look at the buffer it's self and see:
0:022> dc 0x00000000`07560fd0
00000000`07560fd0 0022007b 006f006d 00650064 003a0022 {.".m.o.d.e.".:.
00000000`07560fe0 006d0022 006e0061 00610075 0022006c ".m.a.n.u.a.l.".
00000000`07560ff0 000a007d d0d0fafa d0d0d0d0 d0d0d0d0 }...............
This shows that my buffer has been filled by ReadFile but where the NULL should have been left at buf[36] and buf[37] (remember the memset) there is an app verifier fill code fafa (remember the unicode bytes are flipped so d0d0 is actually after fafa.
I've looked here: which has shown me how app verifier leaves these fill codes after allocations. But fafa is not listed, so what does it mean? And why is it in the place where memset should have cleared?
I don't have a source for this at the moment, but one of the features AppVerifier does is completely fills your buffer with a pattern prior to invoking ReadFile. You request to read 38 bytes, AppVerifier fills your buffer with 38 bytes of pattern, and ReadFile only reads 36 bytes from the file. Thus your last 2 bytes are fill pattern rather than the expected NULL characters.

Getting a string using inline ASM

What I am doing is injecting a DLL into a running process. I then proceed to check some informations about that process, such as versions etc. My problem is I cannot seem to access a string in the assembly file, that contains the revision number I want to doublecheck. Here is what I have so far:
__declspec(naked) void CheckBuild()
{
char* revision;
__asm {
sub esp, __LOCAL_SIZE
pushad
pushfd
mov revision, dword ptr 0x5F5200
}
printf("Detected revision ID: %u\n", revision);
__asm {
popfd
popad
add esp, __LOCAL_SIZE
retn
}
}
For this training stuff, the address of the string, that I get through IDA and that I checked using CheatEngine and OllyDbg, is constant.
However, no matter what I try, I always get 0x5F5200 back in decimal, which is definitely not what I expect. I almost tried everything, including lea and others, but I still don't get the valid string.
Can anyone point me to the correct direction ?
you are missing the "dereferencing":
mov revision, dword ptr [0x5F5200]
which isn't a valid instruction since it has two indirects, so
mov eax, dword ptr [0x5F5200]
mov revision, eax
if the value is indeed a string, there's something else wrong:
if the string is stored at 0x5F5200, you would simply use
printf("Detected revision ID: %s\n", 0x5F5200)
if the address of the string is stored at 0x5F5200, you would use
printf("Detected revision ID: %s\n", revision)
String format
If the string is unicode, you would use
printf("Detected revision ID: %S\n", revision);
(note that with wprintf, it's the other way 'round: %s for a wide character string, and %s for a char string).
Finally, if the string is not guaranteed to be zero-terminated but has a fixed length, you need to copy from the address to a local buffer and ensure zero termination before the print.

gdb to debug double free not detected by valgrind (?)

About once every three times I run my program, malloc reports a double free error; e.g.
myprogram(703,0xb06d9000) malloc: *** error for object 0x17dd0240: double free
*** set a breakpoint in malloc_error_break to debug
I've run the same code through valgrind more than a dozen times but it never reports a double free.
I ran the code through gdb with a breakpoint on malloc_error_break and (when the bug occurs) the error is always reported in a standard c++ library function. I isolated the parent function and valgrinded it in a test unit but no errors.
I think the parent function/standard c++ library is not to blame, it is simply freeing something it allocated but some other function in the parent program freed.
I've tried looking up which object is double freed but my gdb skills aren't up to finding the first object that was freed. Please help me find which object caused the first free and additionally any help to why my progam generates this error. Thank you.
The parent function boils down to:
int i;
double px, py;
int start, finish;
std::string comment;
std::vector<double> x, y;
std::fstream myfile;
myfile.open("filename.txt", std::ios_base::in);
// Read header
std::getline(myfile, comment);
// Read data
while(!myfile.eof())
{
myfile >> comment >> start >> comment >> finish;
for(i = 0; i <= finish-start; i++)
{
myfile >> px >> py; // double free here
x.push_back(px);
y.push_back(py);
}
}
EDIT:
My data file is something like this:
Comment: My Data
start 33 end 36
10.2 139.0076
9.22616 141.584
8.62802 141.083
8.87098 141.813
start 33 end 35
300.354 405
301.698 404.029
303.369 403.953
start 33 end 35
336.201 148.07
334.616 147.243
334.735 146.09
The backtrace from gdb is
(gdb) backtrace
#0 0x93c2d4a9 in malloc_error_break ()
#1 0x93c28497 in szone_error ()
#2 0x93b52503 in szone_free ()
#3 0x93b5236d in free ()
#4 0x93b51f24 in localeconv_l ()
#5 0x93c18163 in strtod_l$UNIX2003 ()
#6 0x93c192e0 in strtod$UNIX2003 ()
#7 0x919b76e8 in std::__convert_to_v<double> ()
#8 0x919983cf in std::num_get<char, std::istreambuf_iterator<char, std::char_traits<char> > >::do_get ()
#9 0x91991671 in std::num_get<char, std::istreambuf_iterator<char, std::char_traits<char> > >::get ()
#10 0x9198d2dc in std::istream::operator>> ()
Just to reiterate, I need help to find which object was freed the first time, I'm not so interested in refactoring my code for this function - which I don't believe is causing the problem; unless you can find something catastrophic in it.
EDIT: Changed the example code.
You appear to be using Mac OSX (you should have divulged that fact :-)
There are several environment variables which can help you debug heap corruption.
In particular, MallocStackLoggingNoCompact looks very promising.
Here is what I see:
$ cat t.c
int main()
{
char *p = strdup("hello");
free(p);
free(p);
return 0;
}
$ gdb ./a.out
GNU gdb 6.3.50-20050815 (Apple version gdb-967) (Tue Jul 14 02:11:58 UTC 2009)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-apple-darwin"...Reading symbols for shared libraries ... done
(gdb) set env MallocStackLoggingNoCompact 1
(gdb) b malloc_error_break
Breakpoint 1 at 0x13f44a9
(gdb) r
Starting program: /Users/emp-russian/a.out
bash(22634) malloc: recording malloc stacks to disk using standard recorder
bash(22634) malloc: stack logging compaction turned off; size of log files on disk can increase rapidly
bash(22634) malloc: process 22536 no longer exists, stack logs deleted from /tmp/stack-logs.22536.a.out.8D3VZO
bash(22634) malloc: stack logs being written into /tmp/stack-logs.22634.bash.kjFTGa
arch(22634) malloc: recording malloc stacks to disk using standard recorder
arch(22634) malloc: stack logging compaction turned off; size of log files on disk can increase rapidly
arch(22634) malloc: stack logs deleted from /tmp/stack-logs.22634.bash.kjFTGa
arch(22634) malloc: stack logs being written into /tmp/stack-logs.22634.arch.8L8iLX
Reading symbols for shared libraries ++. done
Breakpoint 1 at 0x909b54a9
a.out(22634) malloc: recording malloc stacks to disk using standard recorder
a.out(22634) malloc: stack logging compaction turned off; size of log files on disk can increase rapidly
a.out(22634) malloc: stack logs deleted from /tmp/stack-logs.22634.arch.8L8iLX
a.out(22634) malloc: stack logs being written into /tmp/stack-logs.22634.a.out.s1qQRw
a.out(22634) malloc: *** error for object 0x100080: double free
*** set a breakpoint in malloc_error_break to debug
Breakpoint 1, 0x909b54a9 in malloc_error_break ()
(gdb) shell ls -l /tmp/stack-logs.22634.a.out.s1qQRw
total 16
-rw------- 1 emp-russian wheel 96 Sep 12 09:42 stack-logs.index
-rw------- 1 emp-russian wheel 208 Sep 12 09:42 stack-logs.stacks
(gdb) shell malloc_history 22634 0x100080
This first part of the history we don't actually care about:
Call [2] [arg=24]: thread_a0103720 |_dyld_start | dyldbootstrap::start(mach_header const*, int, char const**, long) | dyld::_main(mach_header const*, unsigned long, int, char const**, char const**, char const**) | dyld::initializeMainExecutable() | ImageLoader::runInitializers(ImageLoader::LinkContext const&) | ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) | ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) | ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) | ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) | libSystem_initializer | __keymgr_initializer | _dyld_register_func_for_add_image | dyld::registerAddCallback(void (*)(mach_header const*, long)) | dwarf2_unwind_dyld_add_image_hook | calloc | _malloc_initialize | malloc_set_zone_name | malloc_zone_malloc | __disk_stack_logging_log_stack | reap_orphaned_log_files | opendir$INODE64$UNIX2003 | __opendir2$INODE64$UNIX2003 | telldir$INODE64$UNIX2003 | malloc | malloc_zone_malloc
Call [4] [arg=0]: thread_a0103720 |_dyld_start | dyldbootstrap::start(mach_header const*, int, char const**, long) | dyld::_main(mach_header const*, unsigned long, int, char const**, char const**, char const**) | dyld::initializeMainExecutable() | ImageLoader::runInitializers(ImageLoader::LinkContext const&) | ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) | ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) | ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) | ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) | libSystem_initializer | __keymgr_initializer | _dyld_register_func_for_add_image | dyld::registerAddCallback(void (*)(mach_header const*, long)) | dwarf2_unwind_dyld_add_image_hook | calloc | _malloc_initialize | malloc_set_zone_name | malloc_zone_malloc | __disk_stack_logging_log_stack | reap_orphaned_log_files | closedir$UNIX2003 | _reclaim_telldir | free | malloc_zone_free
But here is the interesting stuff:
Call [2] [arg=6]: thread_a0103720 |0x1 | start | main | strdup | malloc | malloc_zone_malloc
Call [4] [arg=0]: thread_a0103720 |0x1 | start | main | free | malloc_zone_free
Call [4] [arg=0]: thread_a0103720 |0x1 | start | main | free | malloc_zone_free
I am currently trying to track down a "trying to free unallocated pointer" error, also on MacOS. My error is triggered about one in fifty runs (with identical input) of the program, and, of course, it has never happened when I've been running it the debugger (sigh).
What I describe below is a convenient way to get a backtrace on that rare occasion when the bug is triggered, without having to interact with gdb on each run. It is an alternative to EmployedRussian's excellent tips.
Use the following gdb command file:
# malloc_error_break.gdb
break malloc_error_break
run # Add program arguments here
backtrace
Run gdb, executing the command file, like this:
gdb -x malloc_error_break.gdb --batch my_program
If the program runs without hitting the freeing problem, it will print "No stack" in response to the backtrace command, then gdb will exit (thanks to the --batch option).
If the program hits the freeing error, I will (hopefully!) get a stack before gdb exits.
This line:
myfile >> comment
will only read "Comment:" and not the entire line "Comment: My Data". The next thing read from myfile after that line will be "my", which will likely cause problems.
In particular, the first time through the outer loop, it will attempt to read the string "Data" into start, and will be unable to do so (since it can't be parsed as an integer). So the statement:
myfile >> comment >> start >> comment >> finish;
will abort and both start and finish will be left uninitialized.
Depending on the (arbitrary) uninitialized values of start and finish, this could easily make your inner loop infinite. Inserting an infinite number of elements into a vector is likely to lead to strange behavior, although I don't see the crash that you do... it just runs for a very long time and I kill it because I run out of patience.
However, when I work around this bug by removing "My Data" from the first line, I can run your program 10,000 times without a crash.
try running gdb, cont to the crash point, then print the backtrace (type bt); see if that helps you point out where the problem is (note, you have to compile your program in debugging mode, g++ -g, to print a legible backtrace).
EDIT:
On most machine, when you free/delete a memory location the pointer you're freeing is not NULL-ed. At the point where you're free-ing the memory for the second time, try adding a "= NULL", i.e.:
delete myPointer;
myPointer = NULL;
that does NOT fix the problem; however, it will isolate the possibility that the first free()/delete is also that exact same line (but on a previous execution, say, if you're on a loop).
btw, your code snippet doesn't contain any dynamically allocated memory (apart from std::string, which internally allocate memory dynamically).
Have you taken a look into what is the value of start and finish and whether the file has enough contents to fill in vectors x and y?
A better approach would be to re-factor the looping logic -- you should break the moment you hit file EOF. At this point you have left it to faith.