Тема: [FASM] x86 Position-independent code, proof of concept
У якості розминки, наваяв приклад частково позиційно-незалежного коду. Завдяки частковості, ми отримуємо дуже компактне PI-тіло, яке, наприклад, можемо кудись заінжектити.
[img]http://i63.домен агресора/big/2015/0126/0f/207014b4b480eca9a364dae9e4f5d80f.png[/img]
За приклад візьмемо наступний код:
WSADATA wsaData;
char *m, name[128];
WSAStartup(0x202, &wsaData);
gethostname(name, 128);
m = inet_ntoa(*(struct in_addr*)gethostbyname(name)->h_addr_list[0]);
MessageBoxA(0, m, "Заголовок", MB_OK);
WSACleanup();
ExitProcess(0);shellcode.asm
    format pe gui 5.01
    entry start
    include 'win32ax.inc'
    struct APIS
        MessageBoxA     rd 1
        ExitProcess     rd 1
        WSAStartup      rd 1
        gethostname     rd 1
        inet_ntoa       rd 1
        gethostbyname   rd 1
        WSACleanup      rd 1
    ends
    struct CONFIG
        apis        APIS
        wsaData     WSADATA
        name        rb 128
        tittle      rb 20
    ends
;   ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
section '.data' data  readable writeable                                 // секція даних
api_table dd    nMessageBoxA,\
                nExitProcess,\
                nWSAStartup,\
                ngethostname,\
                ninet_ntoa,\
                ngethostbyname,\
                nWSACleanup,\
                -1
    nMessageBoxA    db 'MessageBoxA',       0
    nExitProcess    db 'ExitProcess',       0
    nWSAStartup     db 'WSAStartup',        0
    ngethostname    db 'gethostname',       0
    ninet_ntoa      db 'inet_ntoa',         0
    ngethostbyname  db 'gethostbyname',     0
    nWSACleanup     db 'WSACleanup',        0
    user32          db 'user32',            0
    kernel32        db 'kernel32',          0
    ws2_32          db 'ws2_32',            0
    ttl             db 'Заголовок',         0
    shc             rd                      1
    cfg             rd                      1
    hHeap           rd                      1
shellcode:
    virtual at ebp
        config CONFIG
    end virtuaL
    lea eax, [config.wsaData]
    push eax
    push 0x202
    call [config.apis.WSAStartup]
    push 128
    lea eax, [config.name]
    push eax
    call [config.apis.gethostname]
    lea eax, [config.name]
    push eax
    call [config.apis.gethostbyname]
    mov eax, [eax + hostent.h_addr_list]
    mov eax, [eax]
    push dword[eax]
    call [config.apis.inet_ntoa]
    push 0
    lea edx, [config.tittle]
    push edx
    push eax
    push 0
    call [config.apis.MessageBoxA]
    call [config.apis.WSACleanup]
    push 0
    call [config.apis.ExitProcess]
size_shellcode = $ - shellcode
;   ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
;   ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
section '.text' code  readable executable                                // секція коду
start:
    // аналог GetProcessHeap()
    mov eax, [fs:0x30]
    mov eax, [eax + 0x18]
    mov [hHeap], eax
    // виділяємо пам'ять під структуру
    invoke HeapAlloc, [hHeap], HEAP_ZERO_MEMORY, sizeof.CONFIG
    mov [cfg], eax
    // ..під шеллкод
    invoke HeapAlloc, [hHeap], HEAP_ZERO_MEMORY, size_shellcode
    mov [shc], eax
    // знаходимо адреси winapi
    mov ebx, [cfg]
    mov esi, api_table
.a: cmp dword[esi], nMessageBoxA
    ja @f
    push user32
    jmp .b
@@: cmp dword[esi], nExitProcess
    ja @f
    push kernel32
    jmp .b
@@: push ws2_32
.b: invoke LoadLibraryA
    invoke GetProcAddress, eax, dword[esi]
    mov dword[ebx], eax
    add esi, 4
    add ebx, 4
    cmp dword[esi], -1
    jne .a
    mov ebx, [cfg]
    invoke lstrcpyA, addr ebx + CONFIG.tittle, ttl
    // копіюємо шеллкод у пам'ять
    mov esi, shellcode
    mov edi, [shc]
    mov ecx, size_shellcode
    rep movsb
    // передаєм вказівник на структуру та стартуємо шеллкод
    mov ebp, [cfg]
    push ebp
    jmp [shc]
;   ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
;   ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
section '.idata' import data  readable writeable                         // секція імпорту
    library kernel32, 'kernel32.dll',\
            user32, 'user32.dll'
    import  kernel32,\
            GetProcAddress, 'GetProcAddress',\
            LoadLibraryA, 'LoadLibraryA',\
            HeapAlloc, 'HeapAlloc',\
            lstrcpyA, 'lstrcpyA'
;   ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~[img]http://i58.домен агресора/big/2015/0126/d9/9db084d9a94c691a72908347aa9172d9.png[/img]