Related to this question: In gdb, how can I write a string to memory?
However, my question is regarding how to write non-ASCII characters as well, which I'm having trouble with.
Not only does it seem like I have to specify the number of characters I want to write with
set {char[<number of characters>]}, but I don't seem able to escape characters in my string.
Consider:
set {char [5]} 0x618204 = "ABCD"
This should be equivalent:
set {char [5]} 0x618204 = "ABC\x44"
There is no error, but this treats the string as something else entirely, I'm not even sure what this does.
How can I write a string with escaped characters like this, I want some way to write arbitrary bytes to memory, preferably without needing to tell GDB beforehand how many bytes I intend to write.
I'd like something simple like:
set 0x618204 = \x41\x42\x43\x44\x45
This should write the bytes 0x41 0x42 0x43 0x44 0x45 to memory, starting at the address 0x618204.
Am I just missing the correct syntax for this, or doesn't it exist? Is there some extension to GDB that can do it? gef, peda?
There is no error, but this treats the string as something else entirely
No, it doesn't:
(gdb) start
Temporary breakpoint 1 at 0x1129: file t.c, line 3.
Starting program: /tmp/a.out
Temporary breakpoint 1, main () at t.c:3
3 char buf[] = "abcd";
(gdb) n
4 void *p = buf;
(gdb) n
5 return 0;
(gdb) p p
$1 = (void *) 0x7fffffffdb93
(gdb) p {char[4]}p
$2 = "abcd"
(gdb) set {char[4]}p = "ABC\x44"
Too many array elements
The error here is because char[4] doesn't account for terminating NUL.
(gdb) set {char[5]}p = "ABC\x44"
(gdb) p buf
$3 = "ABCD"
Voila!
You can write in memory with GDB using the set command:
Here is an example of how to change a single byte in memory with GDB:
pwndbg> x/bx 0x7fffffffdb7f
0x7fffffffdb7f: 0x30
pwndbg> set *0x7fffffffdb7f=0x00
pwndbg> x/bx 0x7fffffffdb7f
0x7fffffffdb7f: 0x00
You can also write multiple bytes, but you have to be aware of endianess.
pwndbg> set *0x7fffffffdb78=0x00414243
pwndbg> x/s 0x7fffffffdb78
0x7fffffffdb78: "CBA"
pwndbg> set *0x7fffffffdb78=0x0068732f6e69622f
pwndbg> x/s 0x7fffffffdb78
0x7fffffffdb78: "/bin/sh"
Related
I am trying to add some shellcode in my input to demonstrate buffer overflow leading to control hijacking.
Here is program;
int foo(char *mainbuff)
{
char foobuff[128];
strcpy(foobuff, mainbuff);
printf("foobuff new value is %s\n", foobuff);
return 0;
}
int main()
{
char mainbuff[256];
printf("Please enter value of mainbuff\n\n");
scanf("%s", mainbuff);
foo(mainbuff);
printf("Program is exitting normally!!\n\n\n");
return 0;
}
According to my understanding when I should give \x90 this input to my c program it should take it and store it in memory as a single byte. So when I concatenate nops with shellcode and address my input seems like
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x10\xd2\xff\xff
It should store as single bytes in arrays but compiler adds another \ not to escape them and store them in stack memory as 0x3039785c which is hex form of 09x\. My file which store this string also not exactly the size of bytes I am storing. I am on 64 bit machine but my program is compiled using -m32 option in gcc.
So whats going on here?
I should give \x90 this input to my c program it should take it and store it in memory as a single byte.
It seems you directly typing \x90 as input. This will cause the program (actually, the stdin) to regard it as 4 continuous characters, 0x5c, 0x78, 0x39, 0x30, which is getting endian into your mentioned 0x3039785c.
You may try echo -e "\x90\x90..." | ./a.out to pipe the shellcode into stdin by the escape.
I met a strange problem whne tying to convert a Lua string to C char arry.
local str = "1234567890abcdef"
local ffi = require "ffi"
ffi.cdef[[
int printf(const char *fmt, ...);
]]
print(#str)
print(str)
local cstr = ffi.new("unsigned char[?]", #str, str)
run this code get:
[root#origin ~]# luajit test.lua
16
1234567890abcdef
Segmentation fault
I know ffi.new("unsigned char[?]", #str+1, str) will solve this, but I dont know why.
I don't think it is the \0 problem because I found some strange point.
if str is not 16 bytes, this will not happen.
if I delete ffi.cdef which I didn't use , this will not happen.
if I put ffi.cdef behind the ffi.new ,this will not happen .
[root#origin ~]# luajit test.lua
17
1234567890abcdefg
// this is the result that I only append a 'g' to `str`.
I tried on Luajit 2.0.5 and Luajit 2.1.0-beta3 with default compiler arguments.
So, is there anyone knows how this happen, thanks.
It is exactly because of string size is 17 but array allocated only for 16 bytes. https://github.com/LuaJIT/LuaJIT/blob/0c0e7b168ea147866835954267c151ef789f64fb/src/lj_cconv.c#L582 is the code that copies string to resulting array. As you can see, if target is array and its size is smaller than string length, it shrinks string; however your type is VLA (variable-length array), and for VLA size is not specified (it is 2**32-1, actually, which is way bigger than 17).
"I don't get error if" is not an argument here - you stomp memory that is used for something else. Sometimes stomping extra byte with 0 is not fatal (e.g. due to alignment this byte wasn't used anyway, or just happened to be 0 already) or doesn't result in hard crash - it doesn't make it correct.
In LLDB console on iOS, I repeated
(lldb) p/x $r1
(unsigned int) $1 = 0x07000006
(lldb) p/x $r1
(unsigned int) $2 = 0x07000006
(lldb) p/x $r1
(unsigned int) $3 = 0x07000006
...etc
about 1500 times, and finally got the following error message
error: Couldn't allocate space for the stack frame: Couldn't malloc: address space is full
Errored out in Execute, couldn't PrepareToExecuteJITExpression
As far as I understand it, each time I run p/x $r1, the debugger evaluates $r1 as an expression and allocates a buffer in a memory for a temporary variable $N (where N = 1, 2, 3, ...). After about 1500 evaluations, the debugger run out of memory and can't allocate buffers anymore.
My question is how can I free some memory? E.g. if I do not need the temporary variable $1 anymore, can I do something like free($1)? Are there any "secret" lldb commands for that?
Thanks in advance for your answers.
Are you doing p/x $r1 because you need to preserve value of $r1 in a temporary, or do you just want to see its value? If the latter, you can use:
(lldb) register read/x r1
which can be shortened to:
(lldb) re r/x r1
That directly prints the register without constructing a temporary. Similarly, if you just want to see the value of a local variable:
(lldb) frame variable foo
will print the value of foo without going through the full expression parser.
Note, there is also a bug in the current lldb that causes expressions to allocate way more memory than they need to - 1500 expressions is too few for you to really be running out of memory, even on a 32 bit system... That's been fixed in the lldb.llvm.org sources, but I don't know when the fix will make its way into a release.
There isn't currently a way to tell lldb either not to make, or to discard, these convenience variables. There's no reason this couldn't be done, there just hasn't been a need for it.
Below is the C code
#include <stdio.h>
void read_input()
{
char input[512];
int c = 0;
while (read(0, input + c++,1) == 1);
}
int main ()
{
read_input();
printf("Done !\n");
return 0;
}
In the above code, there should be a buffer overflow of the array 'input'. The file we give it will have over 600 characters in it, all 2's ( ex. 2222222...) (btw, ascii of 2 is 32). However, when executing the code with the file, no segmentation fault is thrown, meaning program counter register was unchanged. Below is the screenshot of the memory of input array in gdb, highlighted is the address of the ebp (program counter) register, and its clear that it was skipped when writing:
LINK
The writing of the characters continues after the program counter, which is maybe why segmentation fault is not shown. Please explain why this is happening, and how to cause the program counter to overflow.
This is tricky! Both input[] and c are in stack, with c following the 512 bytes of input[]. Before you read the 513th byte, c=0x00000201 (513). But since input[] is over you are reading 0x32 (50) onto c that after reading is c=0x00000232 (562): in fact this is little endian and the least significative byte comes first in memory (if this was a big endian architecture it was c=0x32000201 - and it was going to segfault mostly for sure).
So you are actually jumping 562 - 513 = 49 bytes ahead. Than there is the ++ and they are 50. In fact you have exactly 50 bytes not overwritten with 0x32 (again... 0x3232ab64 is little endian. If you display memory as bytes instead of dwords you will see 0x64 0xab 0x32 0x32).
So you are writing in not assigned stack area. It doesn't segfault because it's in the process legal space (up to the imposed limit), and is not overwriting any vital information.
Nice example of how things can go horribly wrong without exploding! Is this a real life example or an assignment?
Ah yes... for the second question, try declaring c before input[], or c as static... in order not to overwrite it.
I'm trying to show a memory print out of the current stack frame, but right now what I have to do is laborious:
# Find out how big the current frame is:
(gdb) print/x $ebp - $esp
$1 = 0x4
# Use that in a display:
(gdb) x/4x $ebp
I'd love to use the define command to make it so this just happens after every step, so I have a constant awareness of the stack frame.
Doing things like these:
(gdb) x/$1x $ebp
(gdb) x/($1)x $ebp
hasn't worked.
In GDB, command x is used to examine the memory with the arguments as follows,
x
x address
x/nfu address
Where n is repeat count, f is display format & u is unit size;
(gdb) p/x $rsp
$4 = 0x7fffffffe248
(gdb) x/4x 0x7fffffffe248
0x7fffffffe248: 0xffffe4e5 0x00007fff 0x00000000 0x00000000
(gdb) x/$4
0x7fffffffe248: 0xffffe4e5
(gdb) x/$4x
Value can't be converted to integer.
(gdb) x/$4 $rsp
A syntax error in expression, near `$rsp'.
(gdb) x/$_
0x7fffffffe248: 0xffffe4e5
Observe the last command x/$_ in which after x, the last address examined is available for use in expressions using $_ variable.
EDIT: The memory content of address produced by variable $_ is given by variable $__.