Hướng dẫn pymem inject python shellcode - pymem tiêm python shellcode

Pymem cho phép bạn tiêm python.dll vào một quy trình đích và sau đó ánh xạ py_run_simple_string với một cuộc gọi đến

class SECTION_HEADER[Structure]:
    _fields_ = [
        ["Name",                    BYTE * 8],
        ["VirtualSize",             DWORD],
        ["VirtualAddress",          DWORD],
        ["SizeOfRawData",           DWORD],
        ["PointerToRawData",        DWORD],
        ["PointerToRelocations",    DWORD],
        ["PointerToLinenumbers",    DWORD],
        ["NumberOfRelocations",     WORD],
        ["NumberOfLinenumbers",     WORD],
        ["Characteristics",         DWORD]
    ]
6.

from pymem import Pymem
import os
import subprocess

notepad = subprocess.Popen[['notepad.exe']]

pm = Pymem['notepad.exe']
pm.inject_python_interpreter[]
filepath = os.path.join[os.path.abspath['.'], 'pymem_injection.txt']
filepath = filepath.replace["\\", "\\\\"]
shellcode = """
f = open["{}", "w+"]
f.write["pymem_injection"]
f.close[]
""".format[filepath]
pm.inject_python_shellcode[shellcode]
notepad.kill[]

Vậy mã đó đã làm gì?

  1. Chúng tôi bắt đầu quy trình Notepad và xử lý của nó

  2. Chúng tôi móc pymem với quy trình notepad

  3. Chúng tôi gọi

    class SECTION_HEADER[Structure]:
        _fields_ = [
            ["Name",                    BYTE * 8],
            ["VirtualSize",             DWORD],
            ["VirtualAddress",          DWORD],
            ["SizeOfRawData",           DWORD],
            ["PointerToRawData",        DWORD],
            ["PointerToRelocations",    DWORD],
            ["PointerToLinenumbers",    DWORD],
            ["NumberOfRelocations",     WORD],
            ["NumberOfLinenumbers",     WORD],
            ["Characteristics",         DWORD]
        ]
    
    6 sẽ:

  • tự động tìm đúng dll python và tiêm nó

  • Đăng ký py_run_simple_stringpy_run_simple_string

  1. Sau đó, chúng tôi tiêm một số mã Python với

    class SECTION_HEADER[Structure]:
        _fields_ = [
            ["Name",                    BYTE * 8],
            ["VirtualSize",             DWORD],
            ["VirtualAddress",          DWORD],
            ["SizeOfRawData",           DWORD],
            ["PointerToRawData",        DWORD],
            ["PointerToRelocations",    DWORD],
            ["PointerToLinenumbers",    DWORD],
            ["NumberOfRelocations",     WORD],
            ["NumberOfLinenumbers",     WORD],
            ["Characteristics",         DWORD]
        ]
    
    8 sẽ:

  • Virtualallocex Một số không gian cho mã được viết some space for the code to be written

  • Viết tải trọng thực tế vào không gian được phân bổ

  • thực thi py_run_simple_string để mã python được giải thích trong quy trình notepadpy_run_simple_string so the python code gets interpreted within the notepad process

  1. Cuối cùng chúng ta thoát khỏi quá trình notepad

13 phút đọc

Nếu bạn thực hiện kiểm tra thâm nhập như công việc hàng ngày của bạn, thường sẽ hữu ích khi đưa cửa hậu vào ứng dụng hợp pháp. Có rất nhiều công cụ ngoài kia có thể thực hiện các loại nhiệm vụ đó, nhưng bạn có biết chúng thực sự hoạt động như thế nào không? Trong bài đăng này, tôi sẽ chỉ cho bạn một phương pháp đơn giản để đưa một cửa hậu vào một thực thi.

Ở đây chúng tôi sẽ sử dụng Python vì nó là một ngôn ngữ thực sự linh hoạt và cũng là một trong những ngôn ngữ được sử dụng nhiều nhất trong điện toán tấn công. Tôi thực sự khuyên bạn nên đọc một trong những bài viết trước của tôi về định dạng thực thi di động để hiểu đầy đủ bài đăng này.

Giới thiệu

Ở đây, mục tiêu là đưa mã nước ngoài vào một thực thi, nhưng chúng tôi vẫn muốn người thực thi ban đầu hoạt động [vì chúng tôi không muốn đưa ra bất kỳ sự nghi ngờ nào từ mục tiêu của chúng tôi]. Dưới đây là ý tưởng toàn cầu về cách chúng tôi sẽ sửa đổi ứng dụng để tiêm cửa sau của chúng tôi:

Có 2 phương pháp chính để tiêm mã cho một thực thi:

  • Thêm một phần vào thực thi, nhưng nó sẽ [một chút] tăng kích thước của thực thi.
  • Thêm mã vào phần trống [hoặc hang mã] của thực thi, nó đã giành được kích thước tăng nhưng dễ dàng phá vỡ chương trình tùy thuộc vào phương pháp bạn sử dụng. Ngoài ra, nó có các hồ linh hoạt tùy thuộc vào mục tiêu thực thi [ít hoặc không có hang mã].

Ở đây, chúng tôi sẽ sử dụng phương pháp đầu tiên vì nó dễ dàng và đáng tin cậy hơn, nhưng nếu bạn muốn thử phương pháp thứ hai, bạn có thể kiểm tra liên kết sau.

Lưu ý: Hãy cẩn thận, nếu bạn chạy một chất chống vi -rút trên máy của bạn, việc sửa đổi cấu trúc của một thực thi có thể được hiểu là một cuộc tấn công của virus và AV sẽ chặn hoặc loại bỏ thực thi của bạn. Bây giờ bạn biết. Be careful, if you run an antivirus on your machine, modifying the structure of an executable could be interpreted as a viral attack and the AV will block or remove your executable. Now you know.

Nhắc nhở nhanh chóng

Trước khi thêm một phần mới, chúng ta cần biết các chi tiết cấu trúc để không phá vỡ thực thi của chúng ta. Trong một thực thi PE, phần bao gồm 2 phần:

  • Phần, chứa mã thực thi.section, containing the executable code.
  • Tiêu đề phần, chứa mô tả của phần [địa chỉ, mã, kích thước, v.v.]section header, containing the description of the section [address, code, size, etc.]

Độ dài tiêu đề phần là 40 byte và theo cấu trúc này:

class SECTION_HEADER[Structure]:
    _fields_ = [
        ["Name",                    BYTE * 8],
        ["VirtualSize",             DWORD],
        ["VirtualAddress",          DWORD],
        ["SizeOfRawData",           DWORD],
        ["PointerToRawData",        DWORD],
        ["PointerToRelocations",    DWORD],
        ["PointerToLinenumbers",    DWORD],
        ["NumberOfRelocations",     WORD],
        ["NumberOfLinenumbers",     WORD],
        ["Characteristics",         DWORD]
    ]

Mỗi trường giúp Windows tải các phần đúng vào bộ nhớ. Ở đây, chúng tôi chỉ quan tâm bởi các trường sau, các trường khác sẽ được khởi tạo ở mức 0.

  • class SECTION_HEADER[Structure]:
        _fields_ = [
            ["Name",                    BYTE * 8],
            ["VirtualSize",             DWORD],
            ["VirtualAddress",          DWORD],
            ["SizeOfRawData",           DWORD],
            ["PointerToRawData",        DWORD],
            ["PointerToRelocations",    DWORD],
            ["PointerToLinenumbers",    DWORD],
            ["NumberOfRelocations",     WORD],
            ["NumberOfLinenumbers",     WORD],
            ["Characteristics",         DWORD]
        ]
    
    9, chứa tên phần có phần đệm null byte nếu kích thước của tên không bằng 8 byte.
  • [[[value_to_align + alignment - 1] / alignment] * alignment]
    
    # Shellcode size = 12345 bytes
    # FileAligment = 512 bytes
    # SectionAligment = 4096 bytes
    
    SizeOfRawData = [[[12345 + 512 - 1] / 512] * 512]
    VirtualSize = [[[12345 + 4096 - 1] / 4096] * 4096]
    
    0, chứa kích thước của phần trong bộ nhớ.
  • [[[value_to_align + alignment - 1] / alignment] * alignment]
    
    # Shellcode size = 12345 bytes
    # FileAligment = 512 bytes
    # SectionAligment = 4096 bytes
    
    SizeOfRawData = [[[12345 + 512 - 1] / 512] * 512]
    VirtualSize = [[[12345 + 4096 - 1] / 4096] * 4096]
    
    1, chứa địa chỉ Virtaul tương đối của phần.
  • [[[value_to_align + alignment - 1] / alignment] * alignment]
    
    # Shellcode size = 12345 bytes
    # FileAligment = 512 bytes
    # SectionAligment = 4096 bytes
    
    SizeOfRawData = [[[12345 + 512 - 1] / 512] * 512]
    VirtualSize = [[[12345 + 4096 - 1] / 4096] * 4096]
    
    2, chứa kích thước của phần trên đĩa.
  • [[[value_to_align + alignment - 1] / alignment] * alignment]
    
    # Shellcode size = 12345 bytes
    # FileAligment = 512 bytes
    # SectionAligment = 4096 bytes
    
    SizeOfRawData = [[[12345 + 512 - 1] / 512] * 512]
    VirtualSize = [[[12345 + 4096 - 1] / 4096] * 4096]
    
    3, chứa phần bù của phần trên đĩa.
  • [[[value_to_align + alignment - 1] / alignment] * alignment]
    
    # Shellcode size = 12345 bytes
    # FileAligment = 512 bytes
    # SectionAligment = 4096 bytes
    
    SizeOfRawData = [[[12345 + 512 - 1] / 512] * 512]
    VirtualSize = [[[12345 + 4096 - 1] / 4096] * 4096]
    
    4, chứa các cờ mô tả các đặc điểm phần [RWX].

Lưu ý: Nó thực sự quan trọng để phân biệt VA [địa chỉ ảo] và RVA [địa chỉ ảo tương đối]. Địa chỉ ảo tương đối là địa chỉ ảo của một đối tượng từ tệp sau khi được tải vào bộ nhớ, trừ địa chỉ cơ sở [thường bằng

[[[value_to_align + alignment - 1] / alignment] * alignment]

# Shellcode size = 12345 bytes
# FileAligment = 512 bytes
# SectionAligment = 4096 bytes

SizeOfRawData = [[[12345 + 512 - 1] / 512] * 512]
VirtualSize = [[[12345 + 4096 - 1] / 4096] * 4096]
5] của hình ảnh tệp. It’s really important to differentiate VA [Virtual Address] and RVA [Relative Virtual Address]. A relative virtual address is the virtual address of an object from the file once it is loaded into memory, minus the base address [often equal to
[[[value_to_align + alignment - 1] / alignment] * alignment]

# Shellcode size = 12345 bytes
# FileAligment = 512 bytes
# SectionAligment = 4096 bytes

SizeOfRawData = [[[12345 + 512 - 1] / 512] * 512]
VirtualSize = [[[12345 + 4096 - 1] / 4096] * 4096]
5] of the file image.

Cuối cùng, chúng tôi phải chăm sóc sự liên kết. Giá trị SWE sẽ được đặt vào tiêu đề phần phải được căn chỉnh theo giá trị được đặt vào

[[[value_to_align + alignment - 1] / alignment] * alignment]

# Shellcode size = 12345 bytes
# FileAligment = 512 bytes
# SectionAligment = 4096 bytes

SizeOfRawData = [[[12345 + 512 - 1] / 512] * 512]
VirtualSize = [[[12345 + 4096 - 1] / 4096] * 4096]
6 của tệp PE.

  • [[[value_to_align + alignment - 1] / alignment] * alignment]
    
    # Shellcode size = 12345 bytes
    # FileAligment = 512 bytes
    # SectionAligment = 4096 bytes
    
    SizeOfRawData = [[[12345 + 512 - 1] / 512] * 512]
    VirtualSize = [[[12345 + 4096 - 1] / 4096] * 4096]
    
    7, căn chỉnh phần trong bộ nhớ.
  • [[[value_to_align + alignment - 1] / alignment] * alignment]
    
    # Shellcode size = 12345 bytes
    # FileAligment = 512 bytes
    # SectionAligment = 4096 bytes
    
    SizeOfRawData = [[[12345 + 512 - 1] / 512] * 512]
    VirtualSize = [[[12345 + 4096 - 1] / 4096] * 4096]
    
    8, liên kết phần trên đĩa.

Không đủ rõ ràng? Hãy nói rằng

[[[value_to_align + alignment - 1] / alignment] * alignment]

# Shellcode size = 12345 bytes
# FileAligment = 512 bytes
# SectionAligment = 4096 bytes

SizeOfRawData = [[[12345 + 512 - 1] / 512] * 512]
VirtualSize = [[[12345 + 4096 - 1] / 4096] * 4096]
8 bằng 512 byte và
[[[value_to_align + alignment - 1] / alignment] * alignment]

# Shellcode size = 12345 bytes
# FileAligment = 512 bytes
# SectionAligment = 4096 bytes

SizeOfRawData = [[[12345 + 512 - 1] / 512] * 512]
VirtualSize = [[[12345 + 4096 - 1] / 4096] * 4096]
7 bằng 4096 byte. Nếu phần mới của bạn chứa 515 byte trên đĩa, giá trị kích thước phần trên đĩa [
[[[value_to_align + alignment - 1] / alignment] * alignment]

# Shellcode size = 12345 bytes
# FileAligment = 512 bytes
# SectionAligment = 4096 bytes

SizeOfRawData = [[[12345 + 512 - 1] / 512] * 512]
VirtualSize = [[[12345 + 4096 - 1] / 4096] * 4096]
2] sẽ là 1024 vì 515> 512, vì vậy chúng tôi làm tròn nó. Điều tương tự đối với
[[[value_to_align + alignment - 1] / alignment] * alignment]

# Shellcode size = 12345 bytes
# FileAligment = 512 bytes
# SectionAligment = 4096 bytes

SizeOfRawData = [[[12345 + 512 - 1] / 512] * 512]
VirtualSize = [[[12345 + 4096 - 1] / 4096] * 4096]
0, nó sẽ bằng 4096 byte, vì 515

Bài Viết Liên Quan

Chủ Đề