I am examining the contents of a memory address using GDB, but don't know if it is being displayed correctly.
(gdb) p (char *)0x8182f40
$4 = 0x8182f40 "XYZ"
(gdb)
(gdb) x/40x 0x8182f40-16
0x8182f30: 0x00000000 0x00000000 0x000000a8 0x00000010
0x8182f40: 0x005a5958 0x00000000 0x00000000 0x00000029
0x8182f50: 0x00000000 0x00000000 0x00010000 0x082439d8
0x8182f60: 0x08199100 0x00000000 0x08000000 0x00002f08
0x8182f70: 0x00000002 0x000000b1 0x00000000 0x00000000
0x8182f80: 0x00000000 0x00000000 0x00000000 0x00000000
0x8182f90: 0x00000000 0x00000000 0x000000d4 0x00000002
0x8182fa0: 0x000003f1 0x00007162 0x00000002 0x08178d00
0x8182fb0: 0x00000000 0x080ef4b8 0x00000000 0x00000000
0x8182fc0: 0x00000000 0x00000000 0x0000021d 0x00000000
Content at 0x8182f40 above is shown as 0x005a5958, but this looks reversed. Is that correct?
Now printing per byte, I get this:
(gdb) x/40bx 0x8182f40-16
0x8182f30: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x8182f38: 0xa8 0x00 0x00 0x00 0x10 0x00 0x00 0x00
0x8182f40: 0x58 0x59 0x5a 0x00 0x00 0x00 0x00 0x00
0x8182f48: 0x00 0x00 0x00 0x00 0x29 0x00 0x00 0x00
0x8182f50: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
This one makes more sense: 0x8182f40: 0x58 0x59 0x5a
X Y Z
How do I correctly interpret these addresses and contents?
That's little endian.
When storing multi-byte values in memory, there are two1 ways to store them:
Lower bytes on lower addresses. This is called Little Endian or Least Significant Byte First (LSB).
Higher bytes on lower addresses. This is called Big Endian or Most Significant Byte First (MSB).
Historically some CPUs were little endian and some were big endian with big endian perhaps more common, but little endian prevailed. In part because the most common ix86 architecture is little endian. The second most common architecture, ARM, can be configured for either and while traditionally many operating systems used it as big endian (including early Linux), recently everybody seems to use it little endian. Main reason is probably to avoid having to check that code ported from ix86 is endian-neutral.
The reason is looks "wrong" is just a conflict of two conventions:
Numbers are written left-to-right with most significant digit first
Content of memory is written left-to-right in order of increasing addresses.
But this is merely a convention. In computer, little endian might be slightly more logical in that given int value x, the equality (char)x == *(char *)&x holds, which is not true in big endian. Of course C specification is careful enough to leave this implementation defined (with char it does not violate strict aliasing rules).
1PDP-11 featured a third way, a special abomination called middle endian, where 16-bit values were little endian, but 32-bit values were composed of the two 16-bit units in big endian.
You may need to set endianness: http://www.delorie.com/gnu/docs/gdb/gdb_130.html
Looks like your GDB is set as Little-Endian. Refer to http://en.wikipedia.org/wiki/Endianness for more details about Endianness.
Related
I made a simple C program to try understand buffer overflows. I am trying to overflow the input buffer so that flag gets changed to true and the program outputs "got here". The program is here (assume you have password.txt with hey in it):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv){
int flag = 0;
char pwd[5];
char input[5];
FILE *f = fopen("password.txt", "r");
fscanf(f, "%s", pwd);
fclose(f);
strcpy(input, argv[1]);
if(strcmp(input, pwd)){
printf("wrong password!\n");
}
else{
flag = 1;
printf("correct password!\n");
}
if(flag){
printf("you got into the secret place\n");
}
return 0;
}
So on the stack we have something like this I guess:
[high addresses]
flag ---> 4 bytes
pwd ---> 8 bytes
input ---> 8 bytes
[low addresses]
So I think I just need to give the program just 17 bytes to overwrite the flag variable. So i gave it aaaaaaaaaaaaaaaaa but that didn't work. I had to give it a 23 times, so 23 bytes. Why is 17 bytes not enough?
Disclaimer: I used Ubuntu 14.04 with gcc version 4.8.4, and complied your
code thusly gcc -m32 -g -ansi -pedantic -Wall temp.c -o temp. Different
compilers, or different options to gcc will, in all probability, give
different results.
I also modified you code slightly to make it easier to find things,
I changed line 6 to int flag = 0x41414141;
I changed line 25 to if(flag==1){
After compilation I run the executable under GDB, with a break point set
on main. And then disassembled main (after setting disassembly-flavor to
Intel), we get:
(gdb) disass
Dump of assembler code for function main:
0x0804857d <+0>: push ebp
0x0804857e <+1>: mov ebp,esp
0x08048580 <+3>: and esp,0xfffffff0
0x08048583 <+6>: sub esp,0x30
0x08048586 <+9>: mov eax,DWORD PTR [ebp+0xc]
0x08048589 <+12>: mov DWORD PTR [esp+0xc],eax
=> 0x0804858d <+16>: mov eax,gs:0x14
0x08048593 <+22>: mov DWORD PTR [esp+0x2c],eax
0x08048597 <+26>: xor eax,eax
0x08048599 <+28>: mov DWORD PTR [esp+0x18],0x41414141
The first four lines are the prolog for main The important thing to
notice is the line sub esp,0x30 where we are setting up the
stack frame for the function. As you can see we are subtracting 48 bytes
from esp. (actually a bit more because we first aligned the stack frame
to a 16-byte boundary).
Now, we can look at where our stack frame is by looking at the values
for ESP and EBP:
(gdb) info registers esp
esp 0xffffd110 0xffffd110
(gdb) info registers ebp
ebp 0xffffd148 0xffffd148
and we can find where things are located in the stack frame;
(gdb) print &pwd
$3 = (char (*)[5]) 0xffffd132
(gdb) print &flag
$4 = (int *) 0xffffd128
(gdb) print &input
$5 = (char (*)[5]) 0xffffd137
(gdb) print &f
$6 = (FILE **) 0xffffd12c
From this we can now deduce our stack layout. This memory image is
taken after running past where the program reads the command line
argument which was the string BBBBB (recall that the ASCII code for B is 0x42, so it is easy to see a sequence of 0x42 bytes)
(gdb) x/56xb $esp
0xffffd110: 0x37 0xd1 0xff 0xff
0xffffd114: 0xbf 0xd3 0xff 0xff
0xffffd118: 0x32 0xd1 0xff 0xff
0xffffd11c: 0xe4 0xd1 0xff 0xff
0xffffd120: 0x02 0x00 0x00 0x00
0xffffd124: 0xe4 0xd1 0xff 0xff
0xffffd128: 0x41 0x41 0x41 0x41 (flag)
0xffffd12c: 0x08 0xb0 0x04 0x08 (f)
0xffffd130: 0xc4 0xf3
0xffffd132: 0x68 0x65 0x79 0x00 0xff (pwd buffer)
0xffffd137: 0x42 0x42 0x42 0x42 0x42 (input buffer)
0xffffd13c: 0x00 0xd5 0x61 0x5d
0xffffd140: 0x60 0x86 0x04 0x08
0xffffd144: 0x00 0x00 0x00 0x00
Also note, that if I set the command line argument to BBBBBBBB we have this
for the contents of our stack frame
(gdb) x/56xb $esp
0xffffd110: 0x37 0xd1 0xff 0xff 0xbc 0xd3 0xff 0xff
0xffffd118: 0x32 0xd1 0xff 0xff 0xe4 0xd1 0xff 0xff
0xffffd120: 0x02 0x00 0x00 0x00 0xe4 0xd1 0xff 0xff
0xffffd128: 0x41 0x41 0x41 0x41 0x08 0xb0 0x04 0x08
0xffffd130: 0xc4 0xf3 0x68 0x65 0x79 0x00 0xff 0x42
0xffffd138: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x00
0xffffd140: 0x60 0x86 0x04 0x08 0x00 0x00 0x00 0x00
Notice that the contents of the flag variable remains unchanged, but the contents of the now overflown input buffer moves toward the top of the stack. Recall that in x86 the stack grows downward (lower memory addresses). Also, because the buffer grows upward is why we can use a buffer overflow to over write stored EIP on the stack.
So on my system, I do not believe that it is possible to overwrite the flag variable with user input. You system might lay things out differently on the stack (you would need to do a similar exercise to verify this).
Also, note that the location of the variable on the stack does not correlate with the order that they are declared in the source file.
You can run into multiple problems when trying this.
The order of the local variable on the stack isn't necessarily in the same order as the one in the code. The compiler is free to rearrange them as he wish.
The compiler often aligns data to boundary for faster execution. This means the space between the different local variable can be much bigger than what you think. It's not uncommon to see stack variable aligned on a 8 or 16 bytes boundary even if it's content is much smaller.
You can get the disassembly of your program with objdump -D or debug it with gdb. This will give you a much better idea of the stack alignment in your program.
I made this simple password verification program, and I'm trying to overflow the buffer array to change the auth variable to 1 and i managed to do it except I can only change the auth variable to the character 1 and not the decimal 1, how can i do it?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
char buffer[16];
int auth=0;
strcpy(buffer, argv[1]);
if(strcmp(buffer,"password")==0)
auth=1;
else
auth=0;
if(auth)
printf("Granted");
return 0;
}
Following information is derived from runs on my Ubuntu-14.04 system using gcc version 4.8.4 as my compiler and gdb version 7.7.1 as my debugger
First, the buffer overflow happens as a result of the strcpy function, and if you overflow buf so that it overwrites the memory location of auth, but the following if-else block will overwrite your changes.
Secondly you can see what is happening by looking at the stack in a debugger. I made a slight modification to you code, by initializing auth to 0xbbbbbbbb (just so I can find here auth is located on the stack).
Setting a break point on main and stepping into the function we can examine the values of the various registers:
(gdb) info reg
rax 0x0 0
rbx 0x0 0
rcx 0x0 0
rdx 0x7fffffffdf30 140737488346928
rsi 0x7fffffffdf18 140737488346904
rdi 0x2 2
rbp 0x7fffffffde30 0x7fffffffde30
rsp 0x7fffffffddf0 0x7fffffffddf0
[... some lines removed ...]
rip 0x400652 0x400652 <main+37>
eflags 0x246 [ PF ZF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
From this we can see that the stack extends from 0x7fffffffddf0 to 0x7fffffffde30. Now stopping right before the call to strcpy, we can take a look at the stack:
(gdb) x/76xb $rsp
0x7fffffffddf0: 0x18 0xdf 0xff 0xff 0xff 0x7f 0x00 0x00
0x7fffffffddf8: 0x1d 0x07 0x40 0x00 0x02 0x00 0x00 0x00
0x7fffffffde00: 0x30 0xde 0xff 0xff 0xff 0x7f 0x00 0x00
0x7fffffffde08: 0x00 0x00 0x00 0x00 0xbb 0xbb 0xbb 0xbb
0x7fffffffde10: 0xd0 0x06 0x40 0x00 0x00 0x00 0x00 0x00
0x7fffffffde18: 0x40 0x05 0x40 0x00 0x00 0x00 0x00 0x00
0x7fffffffde20: 0x10 0xdf 0xff 0xff 0xff 0x7f 0x00 0x00
0x7fffffffde28: 0x00 0x2b 0x25 0x07 0xdd 0x7a 0xc0 0x6d
0x7fffffffde30: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7fffffffde38: 0x45 0x6f 0xa3 0xf7
Looking at this, we can see that auth is located at a memory address of 0x7fffffffde0c.
I set as a command line argument passwordAAAAAAAA111, and now we can single step across the strcpy call and look at memory again:
(gdb) x/76xb $rsp
0x7fffffffddf0: 0x18 0xdf 0xff 0xff 0xff 0x7f 0x00 0x00
0x7fffffffddf8: 0x1d 0x07 0x40 0x00 0x02 0x00 0x00 0x00
0x7fffffffde00: 0x30 0xde 0xff 0xff 0xff 0x7f 0x00 0x00
0x7fffffffde08: 0x00 0x00 0x00 0x00 0xbb 0xbb 0xbb 0xbb
0x7fffffffde10: 0x70 0x61 0x73 0x73 0x77 0x6f 0x72 0x64
0x7fffffffde18: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0x7fffffffde20: 0x31 0x31 0x31 0x31 0x00 0x7f 0x00 0x00
0x7fffffffde28: 0x00 0x2b 0x25 0x07 0xdd 0x7a 0xc0 0x6d
0x7fffffffde30: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7fffffffde38: 0x45 0x6f 0xa3 0xf7
(gdb)
From this, we can see that the value of auth has not be touched (notice the four 0xbb still in memory starting at 0x7fffffffde0c). Also we can now see where the password is stored in memory, it starts at 0x7fffffffde10. The four 'A's that I used are where the four 0x41s are and the four '1's that I used are where the four 0x31s are
So, on my system I do not see a way that you would be able to overflow into the auth variable.
Finally, the question that you originally raised, remember that the command line arguments are treated as a character array, so passing in something line AAAA1 on the command line will result in the array [0x41 0x41 0x41 0x41 0x31] being passed to your program. What you want your program to receive is actually [0x41 0x41 0x41 0x41 0x01 0x00 0x00 0x00] (assuming 32-bit, little endian architecture). There are two issues that you will face,
1. 0x01 is a non-printable character
2. 0x00 being the null terminator will stop the string input at the first null.
There is not alot you can do about the issue 2, with just a simple input; however as others have suggested the solution around issue 1 is to create a driver program that builds the input buffer the way that you want and then passes that to the program.
On windows (resp. Linux), create a bat (resp shell) file like this:
a 0123456789ABCDEFG
(a being the name of your executable)
Then, edit it with an hex editor and change the last G to 01 hex value, save.
If (I say if) you can make sure that the address of your integer value comes after the char buffer (which I could not do using my gcc, since the compiler locates its variable with an implementation-based order), run this script and you will see that the \001 char is passed at the end of first argument.
Note: there's no way at all to pass a 0 (null) character as arguments are null-terminated, so if you want to inject some data or code, you will have to do without the zero character.
I have one local char buffer size 4 that I fill with strcpy of the main argv[1] that has 4 'A' characters. Using gdb I print out my variable and stack information. I then examine the memory contents.
(gdb) info frame
Stack level 0, frame at 0xbffff0e0:
eip = 0x804848e in main (sbov.c:12); saved eip = 0xb7e2fa83
source language c.
Arglist at 0xbffff0d8, args: argc=2, argv=0xbffff174
Locals at 0xbffff0d8, Previous frame's sp is 0xbffff0e0
Saved registers:
ebp at 0xbffff0d8, eip at 0xbffff0dc
(gdb) print &buffer
$8 = (char (*)[1]) 0xbffff0cf
(gdb) x/5xw 0xbffff0cf
0xbffff0cf: 0x41414141 0x00000000 0x00000000 0xe2fa8300
0xbffff0df: 0x000002b7
(gdb) x/32xb 0xbffff0cf
0xbffff0cf: 0x41 0x41 0x41 0x41 0x00 0x00 0x00 0x00
0xbffff0d7: 0x00 0x00 0x00 0x00 0x00 0x83 0xfa 0xe2
0xbffff0df: 0xb7 0x02 0x00 0x00 0x00 0x74 0xf1 0xff
0xbffff0e7: 0xbf 0x80 0xf1 0xff 0xbf 0xea 0xcc 0xfe
After the last 0x41 and before 0x83, what are the 0x00's? Is this just extra space?
Source Code
/* sbov.c */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int
main(int argc, char **argv)
{
if (argc > 1) {
char buffer[4];
strcpy(buffer, argv[1]);
fprintf(stdout, "echo: %s\n", buffer);
}
return 0;
}
Compiler Options
gcc -ggdb -fno-stack-protector
Yes this is for a security class, it is vulnerable to stack overflow on purpose.
I am trying to understand how to read memory address and find out its value using GDB.
In code, I assigned a value:
xyz->a = -1;
In GDB I see this:
(gdb) p xyz->a
$1 = 65535
(gdb) p/x xyz->a
$2 = 0xffff
(gdb) p &(xyz->a)
$3 = (some_type *) 0x172e750
(gdb) x/40xb 0x172e750
0x172e750: 0xff 0xff 0x00 0x00 0x00 0x00 0x00 0x00
0x172e758: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x172e760: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x172e768: 0xc0 0xe0 0x5b 0x01 0x00 0x00 0x00 0x00
0x172e770: 0xd8 0x00 0x00 0x00 0x29 0x00 0x00 0x00
Firstly, how do I read the memory addresses and their values to determine xyz->a value?
Second, looks like there is an Endian issue going on? How do I confirm that?
In memory, they are complements. To confirm endian, you can try to give xyz->a a value such like 0x55aa.
I have web-service which provides me custom format of container which contains H.264 NAL units.
I want to play them via MediaElement in silverlight using custom MediaStreamSource.
According this article I need to set private codec data.
Web service provides me configCodec but in base64 format (looks like "AUIAHv/hABhnQsAe2gMg7+IhAAADAAEAAAMAMo8WLqABAARozgvI")
So, in other platforms (iOS, Android) all I need is set to extra-data property of codec.
codec->extra-data = info;
But in Windows Phone I should provide this info like 00000001 [SPS] 00000001 [PPS].
So, could someone tell me how I can parse provided private data from web-service to get SPS and PPS values from it?
Your data decoded into hex is:
0x01 0x42 0x00 0x1E 0xFF
0xE1
0x00 0x18 (SPS length in bytes)
0x67 0x42 0xC0 0x1E 0xDA 0x03 0x20 0xEF (SPS...)
0xE2 0x21 0x00 0x00 0x03 0x00 0x01 0x00
0x00 0x03 0x00 0x32 0x8F 0x16 0x2E 0xA0 (...SPS)
0x01
0x00 0x04 (PPS length in bytes)
0x68 0xCE 0x0B 0xC8 (PPS)
I don't know what this structure exactly is and where it is rfom, however SPS and PPS are definitely on it.