• XSS.stack #1 – первый литературный журнал от юзеров форума

C | Как получить адрес памяти, по которому загружена программа?

Naraku

floppy-диск
Пользователь
Регистрация
21.09.2019
Сообщения
9
Реакции
5
Собственно, вопрос в шапке. В PEB увидел поле ImageBaseAddress, попытался цепануть оттуда, но там совсем дичь записана, сильно отличающаяся от реального адреса. Все это проверял через отладчик, наблюдая, куда грузится программа.
 
Хз, попробуй это(^_^):
C:
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <psapi.h>
#pragma comment(lib, "psapi.lib")

int main()
{
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId());

    if (NULL != hProcess)
    {
        HMODULE hMod;
        DWORD cbNeeded;

        if (EnumProcessModulesEx(hProcess, &hMod, sizeof(hMod), &cbNeeded, LIST_MODULES_32BIT | LIST_MODULES_64BIT))
        {
            _tprintf(TEXT("-> 0x%p\n"), hMod);
        }
    }
    CloseHandle(hProcess);
    return 0;
}
 
Разобрался с вариантом получения через PEB. Пришлось воспользоваться немного подредактированным вариантом с MSDN. Оставлю под спойлером, может кому еще понадобится.
C:
typedef struct _PEB {
    BYTE                          Reserved1[2];
    BYTE                          BeingDebugged;
    BYTE                          Reserved2[1];
    PVOID Mutant;
    PVOID ImageBaseAddress;
    PPEB_LDR_DATA                 Ldr;
    PRTL_USER_PROCESS_PARAMETERS  ProcessParameters;
} PEB, * PPEB;

typedef struct _PEB64 {
    BYTE Reserved1[2];
    BYTE BeingDebugged;
    BYTE Reserved2[5];
    PVOID64 Mutant;
    PVOID64 ImageBaseAddress;
    PPEB_LDR_DATA LoaderData;
    PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
} PEB64;

int main()
{
#ifdef _WIN64
    INT_PTR peb = __readgsqword(0x60);
    _PEB64* _peb = (_PEB64*)peb;
#else
    INT_PTR peb = __readfsdword(0x30);
    _PEB* _peb = (_PEB*)peb;
#endif
    void* img = _peb->ImageBaseAddress;
   
    return 0;
}

Вариант h0peIess полностью корректный и рабочий. Наверное будет универсальней чем мой, однако мне требовалось избегать winapi функций.
 
Последнее редактирование:
Вариант h0peIess полностью корректный и рабочий. Наверное будет универсальней чем мой, однако мне требовалось избегать winapi функций.
Если без WINAPI, то вариантов может быть несколько, в зависимости от условий запуска твоего шеллкода.
1) Чтение fs сегмента и обращение к TEB/PEB структурам.
2) Через SEH/VEH обработчик перебор АП вверх в поисках MZ-PE заголовка в надежде найти в таблице импорта kernel/ntdll либу, а дальше все как по маслу.
3) Через Int 2E прерывание методом перебора
Код:
; MASM syntax
    xor ebx, ebx
@@:
    mov edx, MM_SHARED_USER_DATA_VA + X86_PAGE_SIZE - sizeof(HANDLE)
    mov eax, ebx
    Int 2eh
    cmp al, 8
    je @f

    inc ebx
    bt ebx, 10
    jnc @b

    ; Failed
@@:
    mov edx, ProbeAddress
    mov eax, ebx
    Int 2eh
    cmp al, 5
    je  NoAccess

    ; Есть доступ

NoAccess:
    ; Нет доступа
4) Возможно есть способ через SYSCALL опкод, не экспериментировал.
И так далее...
 
ну или как 2 варик через стек
Сумел заинтересовать. Каким образом я могу это сделать через стек?
UPD
Если только получить начальный адрес стека и "АП вверх в поисках MZ-PE заголовка", как написал человек выше.
 
Последнее редактирование:
Сумел заинтересовать. Каким образом я могу это сделать через стек?
UPD
Если только получить начальный адрес стека и "АП вверх в поисках MZ-PE заголовка", как написал человек выше.
Через стек считать адрес возврата из функции и далее по накатанной схеме из 2-го пункта.
Но, шеллкод должен находиться в пределах модуля, иначе словишь #AV.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх