In my quest to learn more about the computer in general, I stumbled upon a book which has some chapters about disassembling, the x86 assembly language, and the relationship between C and x86 assembly. Now I have been reading this GDB command but I am unable to fully understand it.
The command, along with its results, follows:
(gdb) x/32xw $esp
0xbffff7e0: 0xb8000ce0 0x08048510 0xbffff848 0xb7eafebc
0xbffff7f0: 0x00000002 0xbffff874 0xbffff880 0xb8001898
0xbffff800: 0x00000000 0x00000001 0x00000001 0x00000000
0xbffff810: 0xb7fd6ff4 0xb8000ce0 0x00000000 0xbffff848
0xbffff820: 0x40f5f7f0 0x48e0fe81 0x00000000 0x00000000
0xbffff830: 0x00000000 0xb7ff9300 0xb7eafded 0xb8000ff4
0xbffff840: 0x00000002 0x08048350 0x00000000 0x08048371
0xbffff850: 0x08048474 0x00000002 0xbffff874 0x08048510
Now, from what I understand, the command that I issue tells the debugger to:
x (first one): examine the memory
32: get 32 of what follows
x: enable hexadecimal representation
w: show me Word size data.
**Note:** I know that I ask about the esp register, but I don't quite fully understand what $ is doing in front of it. When I try not to use it, I get a missing symbol error, so I get it has something to do with reference/de-reference?
What has been bugging me is how did I find all those bytes? Since I am examining a register, who's size is 32 bit, shouldn't I get only 32 bits, or 4 bytes (only 1 row of the above)? If I am correct with my assumption, then were did we find the rest of the data? Does it have to do something with the stack, and a particular stack frame, which I currently am unaware of?
I would appreciate your input so that I can clarify things in my mind.
(gdb) help x
Examine memory: x/FMT ADDRESS.
Giving $esp as the address will make gdb fetch whatever is in that register and use that as the memory address for the x command - and will show you the following 32 words in memory starting at that address.
variables within gdb itself are names prefixed with a $ , gdb sets up predefined variables for all the cpu registers.
If you want to inspect the esp register, use the command info registers esp, as you'll see with your example (x/32xw $esp), the esp register contains the first address shown, 0xbffff7e0
It's giving you 32 words of memory where the esp register is pointing (apparently that register contains the address 0xbffff7e0).
(gdb) x/32xw $esp
it means show me the 32 words field where esp points.
pieces:32,
format:hex ,
size:word (1 word= 32 bit on gdb)
show me the 32 words field where esp points
(hex)0xbffff7e0 - (hex)0xbffff7f0 = (dec)3221223392 - (dec)3221223408 = 16bytes=4words
Related
void deal_msg(unsigned char * buf, int len)
{
unsigned char msg[1024];
strcpy(msg,buf);
//memcpy(msg, buf, len);
puts(msg);
}
void main()
{
// network operation
sock = create_server(port);
len = receive_data(sock, buf);
deal_msg(buf, len);
}
As the pseudocode shows above, the compile environment is vc6 and running environment is windows xp sp3 en. No other protection mechanisms are applied, that is stack can be executed, no ASLR.
The send data is 'A' * 1024 + addr_of_jmp_esp + shellcode.
My question is:
if strcpy is used, the shellcode is generated by msfvenom, msfvenom -p windows/exec cmd=calc.exe -a x86 -b "\x00" -f python,
msfvenom attempts to encode payload with 1 iterations of x86/shikata_ga_nai
after data is sent, no calc pops up, the exploit won't work.
But if memcpy is used, shellcode generated by msfvenom -p windows/exec cmd=calc.exe -a x86 -f python without encoding works.
How to avoid the original program's crash after calc pops up, how to keep stack balance to avoid crash?
Hard to say. I'd use a custom payload (just copy the windows/exec cmd=calc.exe) and put a 0xcc at the start and debug it (or something that will be easily recognizable under the debugger like a ud2 or \0xeb\0xfe). If your payload is executed, you'll see it. Bypass the added instruction (just NOP it) and try to see what can possibly go wrong with the remainder of the payload.
You'll need a custom payload ; Since you're on XP SP3 you don't need to do crazy things.
Don't try to do the overflow and smash the whole stack (given your overflow it seems to be perfect, just enough overflow to control rIP).
See how the target function (deal_msg in your example) behave under normal conditions. Note the stack address when the ret is executed (and if register need to have certain values, this depend on the caller).
Try to replicate that in your shellcode: you'll most probably to adjust the stack pointer a bit at the end of your shellcode.
Make sure the caller (main) stack hasn't been affected when executing the payload. This might happen, in this case reserve enough room on the stack (going to lower addresses), so the caller stack is far from the stack space needed by the payload and it doesn't get affected by the payload execution.
Finally return to the ret of the target or directly after the call of the deal_msg function (or anywhere you see fit, e.g. returning directly to ExitProcess(), but this might be more interesting to return close to the previous "normal" execution path).
All in all, returning somewhere after the payload execution is easy, just push <addr> and ret but you'll need to ensure that the stack is in good shape to continue execution and most of the registers are correctly set.
So i was recently trying to exploit a kernel mode driver (HEVD) and I encountered a problem which doesn't make sense to me.
After i jumped to my shellcode (which resides in usermode and was made executable by VirtualProtect), the thread keeps generating a pagefault. Then the Thread keeps generating this pagefault in an endless loop (it doesn't throw an exception).
So i investegated what kind of page fault was triggered and i got the following output for the pagefault-handler:
Breakpoint 0 hit
nt!KiPageFault+0x8:
fffff806`7d201d08 488dac2480000000 lea rbp,[rsp+80h]
0: kd> dd %rsp + 0x158
ffff9307`717e9768 51dce820 ffffad82 00000011 00000000
ffff9307`717e9778 ee49cf8e 000001a4 00000010 00000000
ffff9307`717e9788 00010206 00000000 717e97a0 ffff9307
ffff9307`717e9798 00000018 00000000 00000003 00000000
ffff9307`717e97a8 c00000bb 00000000 0000004d 00000000
ffff9307`717e97b8 00000018 00000000 00000003 00000000
ffff9307`717e97c8 7a0e643b fffff806 00000000 00000000
ffff9307`717e97d8 55555555 55555555 7a0e8b10 fffff806
Here we see the stack after the page fault occured. The Breakpoint is triggered immediatly after i resume the execution (and yes, the breakpoint is conditional for only this thread). The frame is exactly the same every time the breakpoint was triggered.
So I tried to decode the stackframe. A pagefault pushes some infomation on the stack. I decoded it manually (I don't know a better way to do this) and I got that the following:
RFLAGS 10206
CS 10
RIP 000001a4ee49cf8e
Errcode 11 --> P, I bits set
CR2 000001a4ee49cf8e
This should be right decoded (maybe it's erroneous. The top of the stack was ffff9307`717e9770, so the 0x...11 was the last thing pushed onto the stack). So the errocodes says that the exception is thrown while the page was present and it was during an instruction fetch.
Now: I think this should mean a access violation because of the NX-Bit. But this cannot be because the address is executable, as this snippet shows:
VA 000001a4ee49cf8e
PXE at FFFFA8D46A351018 PPE at FFFFA8D46A203498 PDE at FFFFA8D440693B90 PTE at
FFFFA880D27724E0
contains 8A00000027704867 contains 0A0000010DA05867 contains 0A0000010F9BE867 contains
0100000119B6C825
pfn 27704 ---DA--UW-V pfn 10da05 ---DA--UWEV pfn 10f9be ---DA--UWEV pfn 119b6c ----A-
UREV
The executable bit is set for the pte. So I asked myself why this happens. It's a bit weird also that it doesn't throw a access-violation and create a bugcheck.
Also the OS runs on virtualbox. I looked up the settings and I noticed that SMEP and SMAP aren't supported by my virtual machine (but by my host system. VirtualBox catches cpuid-Instructions and pretends that this feature is disabled). So this shoudn't be the problem either. Also if you dump the register, the SMEP/SMAP bits in CR4 are not set.
I have really no clue what could be the cause of this problem. Maybe it's because of the virtual machine. It could also be because Windows gets confused when a thread runs userocde or something else. I really thought a long time about it but maybe I just overlookeda a simple reason.
Thanks in advance
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 have a problem about erlang.
One of my Erlang node crashes, and generates erl_crash.dump with reason no more index entries in atom_tab (max=1048576).
i checked the dump file and i found that there are a lot of atoms in the form of 'B\2209\000..., (about 1000000 entries)
=proc:<0.11744.7038>
State: Waiting
Name: 'B\2209\000d\022D.
Spawned as: proc_lib:init_p/5
Spawned by: <0.5032.0>
Started: Sun Feb 23 05:23:27 2014
Message queue length: 0
Number of heap fragments: 0
Heap fragment data: 0
Reductions: 1992
Stack+heap: 1597
OldHeap: 1597
Heap unused: 918
OldHeap unused: 376
Program counter: 0x0000000001eb7700 (gen_fsm:loop/7 + 140)
CP: 0x0000000000000000 (invalid)
arity = 0
do you have some experience about what they are?
Atoms
By default, the maximum number of atoms is 1048576. This limit can be raised or lowered using the +t option.
Note: an atom refers into an atom table which also consumes memory. The atom text is stored once for each unique atom in this table. The atom table is not garbage-collected.
I think that you produce a lot of atom in your program, the number of atom reach the number limition for atom.
You can use this +t option to change the number limition of atom in your erlang VM when your start your erlang node.
So it tells you, that you generate atoms. There is somewhere list_to_atom/1 which is called with variable argument. Because you have process with this sort of name, you register/2 processes with this name. It is may be your code or some third party module what you use. It's bad behavior. Don't do that and don't use modules which is doing it.
To be honest, I can imagine design where I would do it intentionally but it is very special case and it is obviously not the case when you ask this question.
Segments of memory - BSS, Stack, Heap, Data, Code/Text (Are there any more?).
Say I have a 128MB RAM, Can someone tell me:
How much memory is allocated for each of these memory segments?
Where do they start? Please specify the address range or something like that for better clarity.
What factors influence which should start where?
That question depends on the number of variables used. Since you did not specify what compiler or language or even operating system, that is a difficult one to pin down on! It all rests with the operating system who is responsible for the memory management of the applications. In short, there is no definite answer to this question, think about this, the compiler/linker at runtime, requests the operating system to allocate a block of memory, that allocation is dependent on how many variables there are, how big are they, the scope and usage of the variables. For instance, this simple C program, in a file called simpletest.c:
#include <stdio.h>
int main(int argc, char **argv){
int num = 42;
printf("The number is %d!\n", num);
return 0;
}
Supposing the environment was Unix/Linux based and was compiled like this:
gcc -o simpletest simpletest.c
If you were to issue a objdump or nm on the binary image simpletest, you will see the sections of the executable, in this instance, 'bss', 'text'. Make note of the sizes of these sections, now add a int var[100]; to the above code, recompile and reissue the objdump or nm, you will find that the data section has appeared - why? because we added a variable of an array type of int, with 100 elements.
This simple exercise will prove that the sections grows, and hence the binary gets bigger, and it will also prove that you cannot pre-determine how much memory will be allocated as the runtime implementation varies from compiler to compiler and from operating system to operating system.
In short, the OS calls the shot on the memory management!
you can get all this information compiling your program
# gcc -o hello hello.c // you might compile with -static for simplicity
and then readelf:
# readelf -l hello
Elf file type is EXEC (Executable file)
Entry point 0x80480e0
There are 3 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x08048000 0x08048000 0x55dac 0x55dac R E 0x1000
LOAD 0x055dc0 0x0809edc0 0x0809edc0 0x01df4 0x03240 RW 0x1000
NOTE 0x000094 0x08048094 0x08048094 0x00020 0x00020 R 0x4
Section to Segment mapping:
Segment Sections...
00 .init .text .fini .rodata __libc_atexit __libc_subfreeres .note.ABI-tag
01 .data .eh_frame .got .bss
02 .note.ABI-tag
The output shows the overall structure of hello. The first program header corresponds to the process' code segment, which will be loaded from file at offset 0x000000 into a memory region that will be mapped into the process' address space at address 0x08048000. The code segment will be 0x55dac bytes large and must be page-aligned (0x1000). This segment will comprise the .text and .rodata ELF segments discussed earlier, plus additional segments generated during the linking procedure. As expected, it's flagged read-only (R) and executable (X), but not writable (W).
The second program header corresponds to the process' data segment. Loading this segment follows the same steps mentioned above. However, note that the segment size is 0x01df4 on file and 0x03240 in memory. This is due to the .bss section, which is to be zeroed and therefore doesn't need to be present in the file. The data segment will also be page-aligned (0x1000) and will contain the .data and .bss ELF segments. It will be flagged readable and writable (RW). The third program header results from the linking procedure and is irrelevant for this discussion.
If you have a proc file system, you can check this, as long as you get "Hello World" to run long enough (hint: gdb), with the following command:
# cat /proc/`ps -C hello -o pid=`/maps
08048000-0809e000 r-xp 00000000 03:06 479202 .../hello
0809e000-080a1000 rw-p 00055000 03:06 479202 .../hello
080a1000-080a3000 rwxp 00000000 00:00 0
bffff000-c0000000 rwxp 00000000 00:00 0
The first mapped region is the process' code segment, the second and third build up the data segment (data + bss + heap), and the fourth, which has no correspondence in the ELF file, is the stack. Additional information about the running hello process can be obtained with GNU time, ps, and /proc/pid/stat.
example taken from:
http://www.lisha.ufsc.br/teaching/os/exercise/hello.html
memory depend on the global variable and local variable