I'm trying to make a simple buffer overflow tutorial that runs the program below as a service on port 8000 via xinetd. Code was compiled using
gcc -o bof bof.c -fno-stack-protector
ubuntu has stack protection turned off as well.
Exploiting locally i.e
python -c ---snippet--- | ./bof
is successful and the hidden function was executed, displaying text file contents.
However, running it as a service and performing
python -c ---snippet--- | nc localhost 8000
returns nothing when exploiting. Am I missing something here?
#include <stdio.h>
void secret()
{
int c;
FILE *file;
file = fopen("congratulations.txt", "r");
if (file) {
while ((c= getc(file)) !=EOF)
putchar(c);
fclose(file);
}
void textdisplay()
{
char buffer[56];
scanf("%s", buffer);
printf("You entered: %s\n", buffer);
}
int main()
{
textdisplay();
return 0;
}
Output is buffered by default. To disable this you can do the following at the top of main:
setbuf(stdin, NULL);
This should fix your issue.
This is an issue that I am running into as well. Almost exactly the same.
However, here is one piece that I have found out that might be helpful to you. I believe the issue has something to do with xinetd not executing the binary as a terminal and having job control.
So what I did was to have xinetd do:
server = /usr/bin/python
server_args = /opt/shell.py
Then within the /opt/shell.py I had:
import pty
pty.spawn("/opt/oflow.elf")
/opt/oflow.elf being my overflowed binary
When I do this, I can actually send and receive data. Thats when I run the following command via netcat to try and overflow the service remotely:
**printf "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80AAAAAAAAAAAAAAAAAAAAAAAAABCDEFGHIJKLMNOPQ\x7c\xfc\xff\xbf" | nc 192.168.1.2 9000**
This does nothing. However, I test the local version and it works PERFECTLY. Works every time.
Not when its being wrapped in a python pty and xinetd.
When I run the xinetd pointing directly to /opt/oflow.elf, I get absolutely nothing back from netcat.
So that doesn't exactly answer your question but it should whittle it down for you.
UPDATED COMPLETE ANSWER:
I figured out why this wasnt working. No need to use python at all. After every printf statement you must also include:
fflush(stdout);
Otherwise, xinetd doesnt know to send the stdout.
You may also need to do this for stdin:
fflush(stdin);
Related
I'm new to both Linux and C development, trying to take a screenshot in C with the X11 libs.
If I compile and run my program normally, the screenshot is properly taken with no issues. If I run my program as a service, like
sudo systemctl start screenshot
The program fails. Both the logs and analyzing the coredump with GDB only say
Program terminated with signal SIGSEGV, Segmentation fault.
I have set up manual logging in my code:
int main(int argc, char** argv ){
FILE *fp = fopen("log.txt", "w");
setvbuf(fp, NULL, _IONBF, 1024);
fputs("2", fp);
Display* display = XOpenDisplay(NULL);
fputs("5", fp);
Window root = DefaultRootWindow(display);
fputs("6", fp);
When run as a service, log.txt contains the sequence 25. If run from terminal like ./screenshot, the program terminates normally.
Any hints on finding the cause of the issue would be appreciated.
David pointing out to check whether display is NULL and some searching revealed that the issue is that the program can't open the display when running as a service.
Based on this Question: https://unix.stackexchange.com/questions/537628/error-cannot-open-display-on-systemd-service-which-needs-graphical-interface
Setting Environment in the systemd service file as
Environment=DISPLAY=:0.0
Environment=XAUTHORITY=/home/<username>/.Xauthority
resolved the problem and the service runs without issues.
I am trying to understand basics of RPC using RPCGen. I followed a basic tutorial and wrote the follwing myrpc.x file
program MESSAGEPROG {
version EVALMESSAGEVERS {
int EVALMESSAGE(string) = 1;
} = 1;
} = 0x20000002;
I compile it by running
rpcgen -a -C myrpc.x
In the resulting server.c file, I added a printf statement as below
printf("Message is: %s,\n", *argp);
Then i run make -f Makefile.myrpc and start the server by running myrpc_server. Now when i run the client 'myrpc_client', I get the following message printed in the server
Message is: H���5�
Now my question is from where does this argument come from "H���5�" as this is not the argument which i am when running the client? Also can someone explain me how do i start running complex programs with rpcgen?
The garbage value is from code on line 15 in client.c, where is uninitialized variable used as an argument for your rpc call. My version of rpc show an error:
call failed: RPC: Can't encode arguments"
15 char * evalmessage_1_arg;
"How do I start running complex programs with rpc?" It' just on you. We cannot say when you need to use rpc. You probably have some reason for what you chose this implementation.
Some use case for rpc is thin client on slow computer, which needs some expensive computation. Client sends data to powerful server, that do the hard work and returns result.
One cool feature of netcat is how it can turn any command line program into a server. For example, on Unix systems we can make a simple date server by passing the date binary to netcat so that it's stdout is sent through the socket:
netcat -l -p 2020 -e date
Then we can invoke this service from another machine by simply issuing the command:
netcat <ip-address> 2020
Even a shell could be connected (/bin/sh), although I know this is highly unrecommended and has big security implications.
Similarly, I tried to make my own simple C program that both reads and writes from stdin and stdout:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
char buffer[20];
printf("Please enter your name:\n");
fgets(buffer, 20, stdin);
printf("Hello there, %s\n", buffer);
return 0;
}
However, when I invoke the service from another terminal, there is no initial greeting; in fact the greeting is only printed after sending some information. For example:
user#computer:~$ netcat localhost 2020
User
Please enter your name:
Hello there, User
What do I need to do so that my greeting will be sent through the socket initially, then wait for input, then send the final message (just like I am invoking the binary directly)?
I know there may be better (and possibly more secure) approaches to implement such a system, but I am curious about the features of netcat, and why this does not work.
There's a high chance stdout is not line-buffered when writing to a non-terminal. Do an fflush(stdout) just after the printf.
Having read the relevant docs and tutorials and found a similar question, I am still unable to proceed. My aplogies in advance if this is a common question. I did searches but I wasn't really sure what I was looking for...
I am experimenting with the Libssh for C in Debian.
rc = ssh_channel_request_exec(channel, "ls -l");
if (rc != SSH_OK) {
ssh_channel_close(channel);
ssh_channel_free(channel);
return rc;
}
This returns SSH_OK to state that the command was sent successfully. As I understand from a similar question this is because the return listens for the successful 'sending' of the command. The return does not listen to see if it has been successfully executed.
My questions is, how can I:
Execute the command (which by the above function presently does not execute it merely sends the command)
Listen for it's execution
print the returning output?
I am aware of the ssh_channel_read() function but as the command never executes, I usually get the output
Read (256) buffered : 0 bytes. Window: 64000
Take a look at examples/exec.c in the libssh source code!
I want to use a C program to get if the ip of the network interface is set manually or via dhcp.
I've tried to use the following code and it has worked in Debian, but it hasn't worked in OpenWrt. I want to know how to write a C program doing this in OpenWrt.
I have tried to use this:
#include <stdio.h>
int main(void)
{
FILE *fp;
char buffer[80];
fp=popen("cat /etc/network/interfaces |grep ^iface\\ br-lan | awk -F ' ' '{print $4}'","r");
fgets(buffer, sizeof(buffer), fp);
printf("%s", buffer);
pclose(fp);
}
This code is working in Debian, but it isn't working normally in OpenWrt, so I want to know how to write a program to get the same result.
for OpenWRT you can get a such information with the following command:
$uci get network.lan.proto
so I take the program you put in your question and I change only the command used to get information:
#include <stdio.h> <br>
int main(void)
{
FILE *fp;
char buffer[80];
fp=popen("uci get network.lan.proto","r");
fgets(buffer, sizeof(buffer), fp);
printf("%s", buffer);
pclose(fp);
}
to see all network interfaces available in your OpenWRT you can use the following command:
$uci show network
You can avoid using calling linux command in your c by using the libuci. The libuci contains C function to execute uci commands without passing via popen ( popen is used to execute external command from shell).
The libuci exist by default in the development environment of OpenWRT, not need to download it, no need to build it and no need to install it on your OpenWRT machine
You can use libuci in this way
#include <uci.h>
void main()
{
char path[]="network.lan.proto";
char buffer[80];
struct uci_ptr ptr;
struct uci_context *c = uci_alloc_context();
if(!c) return;
if ((uci_lookup_ptr(c, &ptr, path, true) != UCI_OK) ||
(ptr.o==NULL || ptr.o->v.string==NULL)) {
uci_free_context(c);
return;
}
if(ptr.flags & UCI_LOOKUP_COMPLETE)
strcpy(buffer, ptr.o->v.string);
uci_free_context(c);
printf("%s\n", buffer);
}
(Not tested)
and when you compile your program you have to add the -luci in the compilation command gcc
There's no required way for an OS to decide how an interface should be configured. The kernel (the Linux part of e.g. GNU/Linux) doesn't decide, it doesn't (and shouldn't) care, it just gets told which network addresses go with which interfaces by whatever configuration system the OS is using. OpenWRT's not GNU, it operates differently.
There is AFAIK no definitive way.
Reading the interfaces file would be a hint only: there is no guarantee that the current seup came from there.
You could look at 'asking' the DBUS interface if there is one.
You could check for a dhclient process running.
You could check other files in /etc that specify network setup on different distros.
I think the most reliable option would be a multi-layered thing: check a whole host of hints to come up with the answer.
Another option: send a DHCP check packet to the dhcp server to verify the address.. if you don't get an answer though it could be that the network is down but was up when the address was allocated.