Как получить адрес глобальной переменной исполняемой программы через pin и libelf.h - PullRequest
0 голосов
/ 21 мая 2019

Я хочу разработать pintool, чтобы узнать адрес глобальной переменной моей C-программы. Предположим, у меня есть C-программа, в которой у меня было несколько переменных Global указателя. Когда я запускаю ту же программу с помощью pintool, я хочу найти адрес этой глобальной переменной через pintool.

Я пытаюсь получить адрес глобальной переменной через контакт ,, но мы все знают, что Пин, кажется, не обеспечивает такую ​​функциональность. Согласно документации: «Объекты символов предоставляют только информацию о символах функций в приложении. Информация о других типах символов (например, символах данных) должна быть получена инструментом независимо, кажется, что libelf.h может получить адрес глобальной переменной Пожалуйста, помогите мне и подскажите, как я могу это сделать?

1 Ответ

0 голосов
/ 22 мая 2019

Я бы хотел сделать только комментарий, но он слишком длинный ...

Глобальные переменные по определению находятся в исполняемом файле (точнее, в разделе .data или .bss в зависимости от того, являются ли ониинициализирован или нет).Другие переменные размещаются (либо в стеке, либо в куче).

Вам даже не нужны символы, чтобы проверить, находится ли переменная (с учетом ее адреса) в одном из исполняемых разделов или нет: используйте инструментальные функции изображения (IMG_xxx), зацикливайтесь вокруг разделов (SEC_xxx) получить основу и конец разделов, проверить, какой это (.data или .bss).Вы можете получить тип раздела с помощью PIN-кода, используя SEC_Type;если у вас есть адрес, если он находится внутри .bss или .data, то у вас есть глобальная переменная.

Теперь, если вам нужно имя переменной, которая находится по данному адресу, это более сложно икак гласит документация PIN, вам понадобится символическая информация.Я не знаю, может ли libelf сделать это легко, но libdwarf может.Вы также можете проверить код llvm-dwarfdump с открытым исходным кодом, который также может это делать.


note : я провел эксперименты на Windows (раздел .data)но вывод должен быть несколько похож на Linux.

Вот небольшой пример с одной известной глобальной переменной;скомпилировано без оптимизации:

#include <iostream>

int global_counter; // global

void count(const int i)
{
    int local_counter = 0;  // local

    for(int j = 0; j < i; j++)
    {
        global_counter += 1;
        if(j % 2 == 0) {
            local_counter += 1;
        }
    }

    std::cout << "local counter: " << local_counter << std::endl;
}


int main(int argc, char** argv)
{
    if(argc < 2) {
        return -1;
    }

    const auto i = std::atoi(argv[1]);
    if (i >= 0) {
        count(i);

        std::cout << "global counter: " << global_counter << std::endl;
    }

    return 0;
}

Вот разборка части функции count, в которой используется глобальная переменная:

00007FF7077B10BE  | 8B | mov eax,dword ptr ds:[<global_counter>]                       | PinTestSimpleTarget.cpp:14
00007FF7077B10C4  | FF | inc eax                                                       |
00007FF7077B10C6  | 89 | mov dword ptr ds:[<global_counter>],eax                       |
00007FF7077B10CC  | 8B | mov eax,dword ptr ss:[rsp+20]                                 | PinTestSimpleTarget.cpp:15
00007FF7077B10D0  | 99 | cdq                                                           |
00007FF7077B10D1  | 83 | and eax,1                                                     |
00007FF7077B10D4  | 33 | xor eax,edx                                                   |
00007FF7077B10D6  | 2B | sub eax,edx                                                   |
00007FF7077B10D8  | 85 | test eax,eax                                                  |
00007FF7077B10DA  | 75 | jne pintestsimpletarget.7FF7077B10E6                          |

Разборка std :: coutв глобальной переменной:

00007FF7077B117A  | 8B | mov edx,dword ptr ds:[<global_counter>]                       |
00007FF7077B1180  | 48 | mov rcx,rax                                                   | rax:$LN23
00007FF7077B1183  | FF | call qword ptr ds:[<&??6?$basic_ostream@DU?$char_traits@D@std |

Обратите внимание на 3 адреса:

  • 00007FF7077B10BE (чтение)
  • 00007FF7077B10C6 (запись)
  • 00007FF7077B117A (std :: cout)

Сама глобальная переменная имеет вид:

  • 00007FF7077B5628

Вот источник пинтоин (примечание:по неизвестной причине я не смог заставить CRT правильно инициализироваться при использовании std::cout, поэтому я прибегнул к использованию printf вместо этого.

#include "pin.H"

typedef struct _BOUNDARIES
{
    ADDRINT lowest_address;
    ADDRINT highest_address;

    std::string to_str() const
    {
        std::stringstream stream;
        stream << "Low Addr: " << std::hex << lowest_address <<
            "; High Addr: " << highest_address;
        return std::string(stream.str());
    }

    bool is_in_bounds(const ADDRINT addr) const
    {
        return addr >= lowest_address && addr < highest_address;
    }

} BOUNDARIES;

/* ================================================================== */
// Global variables 
/* ================================================================== */
BOUNDARIES main_executable_boundaries;
BOUNDARIES data_section_boundaries;


/* ===================================================================== */
// Utilities
/* ===================================================================== */

/*!
 *  Print out help message.
 */
INT32 Usage()
{
    //std::cout << "[PINTOOL] This tool display the addresses of global variables in the .data section " << std::endl;
    printf("[PINTOOL] This tool display the addresses of global variables in the .data section\n");
    return -1;
}

/* ===================================================================== */
// Analysis routines
/* ===================================================================== */

// analysis for memory read
VOID record_mem_read(ADDRINT ip, ADDRINT addr)
{
    if(data_section_boundaries.is_in_bounds(addr))
    {
        printf("[PINTOOL] Read on a global variable (.data); Instruction addr: %p; Read addr: %p\n", ip, addr);
    }
}

// analysis for memory write
VOID record_mem_write(VOID* ip, ADDRINT addr)
{
    if (data_section_boundaries.is_in_bounds(addr))
    {
        printf("[PINTOOL] Write on a global variable (.data); Instruction addr: %p; Write addr: %p\n", ip, addr);
    }
}

/* ===================================================================== */
// Instrumentation callbacks
/* ===================================================================== */

VOID instrument_instruction(INS ins, VOID *v)
{
    // must be valid and within bounds of the main executable.
    if(!INS_Valid(ins) || !main_executable_boundaries.is_in_bounds(INS_Address(ins))) {
        return;
    }

    const UINT32 mem_operands = INS_MemoryOperandCount(ins);

    // Iterate over each memory operand of the instruction.
    for (UINT32 memOp = 0; memOp < mem_operands; memOp++)
    {
        if (INS_MemoryOperandIsRead(ins, memOp))
        {
            INS_InsertPredicatedCall(
                ins, IPOINT_BEFORE, reinterpret_cast<AFUNPTR>(record_mem_read),
                IARG_INST_PTR,
                IARG_MEMORYOP_EA, memOp,
                IARG_END);
        }

        if (INS_MemoryOperandIsWritten(ins, memOp))
        {
            INS_InsertPredicatedCall(
                ins, IPOINT_BEFORE, reinterpret_cast<AFUNPTR>(record_mem_write),
                IARG_INST_PTR,
                IARG_MEMORYOP_EA, memOp,
                IARG_END);
        }
    }
}

VOID image_load(IMG img, VOID* v)
{
    printf("[PINTOOL] Loading image: %s; Image ID: %i\n",IMG_Name(img).c_str(), IMG_Id(img));
    if(IMG_IsMainExecutable(img)) {
        // register lowest and highest addresses to restrict the trace between those addresses.
        main_executable_boundaries.lowest_address = IMG_LowAddress(img);
        main_executable_boundaries.highest_address = IMG_HighAddress(img);
        printf("Main executable boundaries: %s\n", main_executable_boundaries.to_str().c_str());

        // cycle through all sections of the main executable.
        for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec))
        {
            // get boundaries of the '.data' section
            if(SEC_Name(sec) == ".data") {
                const auto sec_address = SEC_Address(sec);
                data_section_boundaries.lowest_address = sec_address;
                data_section_boundaries.highest_address = sec_address + SEC_Size(sec);                
                printf("Data section boundaries: %s\n", data_section_boundaries.to_str().c_str());
            }
        }
    }
}

VOID image_unload(IMG img, VOID* v)
{
    printf("[PINTOOL] Unloading image: %s\n", IMG_Name(img).c_str());
}

VOID fini(INT32 code, VOID *v)
{
    printf("[PINTOOL] Instrumentation tear down.\n");
}

/* ===================================================================== */
// Main
/* ===================================================================== */

int main(int argc, char *argv[])
{
    //std::cerr << "[PINTOOL] Loading." << std::endl;

    // Initialize PIN library. Print help message if -h(elp) is specified
    // in the command line or the command line is invalid 
    if( PIN_Init(argc,argv) )
    {
        return Usage();
    }

    // Register Instruction to be called to instrument instructions
    INS_AddInstrumentFunction(instrument_instruction, nullptr);

    // Register ImageLoad to be called when an image is loaded
    IMG_AddInstrumentFunction(image_load, nullptr);

    // Register ImageUnload to be called when an image is unloaded
    IMG_AddUnloadFunction(image_unload, nullptr);

    // Register function to be called when the application exits
    PIN_AddFiniFunction(fini, nullptr);

    //std::cerr << "[PINTOOL] Starting instrumentation." << std::endl;

    // Start the program, never returns
    PIN_StartProgram();

    return 0;
}

  • .\pin.exe -t MyPinTool.dll -- PinTestSimpleTarget.exe 6

output:

[PINTOOL] Loading image: G:\Appdata\CPP\PinTestSimpleTarget\x64\Release\PinTestSimpleTarget.exe; Image ID: 1
Main executable boundaries: Low Addr: 7ff7077b0000; High Addr: 7ff7077b8fff
Data section boundaries: Low Addr: 7ff7077b5000; High Addr: 7ff7077b5640
[PINTOOL] Loading image: C:\WINDOWS\System32\KERNELBASE.dll; Image ID: 2
[PINTOOL] Loading image: C:\WINDOWS\System32\KERNEL32.DLL; Image ID: 3
[PINTOOL] Loading image: C:\WINDOWS\SYSTEM32\ntdll.dll; Image ID: 4
[PINTOOL] Loading image: C:\WINDOWS\System32\ucrtbase.dll; Image ID: 5
[PINTOOL] Loading image: C:\WINDOWS\SYSTEM32\VCRUNTIME140.dll; Image ID: 6
[PINTOOL] Loading image: C:\WINDOWS\SYSTEM32\MSVCP140.dll; Image ID: 7
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1ed1; Read addr: 0x7ff7077b5008
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1f63; Write addr: 0x7ff7077b5000
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1cb6; Read addr: 0x7ff7077b55c0
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1cc7; Write addr: 0x7ff7077b55c0
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b2265; Write addr: 0x7ff7077b501c
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b2271; Write addr: 0x7ff7077b5018
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b22c0; Read addr: 0x7ff7077b5020
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b22c0; Write addr: 0x7ff7077b5020
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b2310; Read addr: 0x7ff7077b5624
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b233f; Write addr: 0x7ff7077b5624
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b234d; Write addr: 0x7ff7077b5018
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b2357; Write addr: 0x7ff7077b501c
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b238b; Read addr: 0x7ff7077b501c
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b2394; Write addr: 0x7ff7077b5018
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b239e; Write addr: 0x7ff7077b501c
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b23ad; Write addr: 0x7ff7077b5018
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b23b7; Write addr: 0x7ff7077b501c
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b23d2; Read addr: 0x7ff7077b5030
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1c97; Read addr: 0x7ff7077b55b8
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1c97; Write addr: 0x7ff7077b55b8
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1998; Read addr: 0x7ff7077b55b0
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b19ab; Write addr: 0x7ff7077b55b0
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1d02; Read addr: 0x7ff7077b55c1
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b23d2; Read addr: 0x7ff7077b5030
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1d4f; Write addr: 0x7ff7077b55c8
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1d57; Write addr: 0x7ff7077b55d8
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1d5e; Write addr: 0x7ff7077b55e0
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1d66; Write addr: 0x7ff7077b55f0
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1d6d; Write addr: 0x7ff7077b55c1
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1e76; Read addr: 0x7ff7077b55c8
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1fca; Read addr: 0x7ff7077b5014
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1fb5; Read addr: 0x7ff7077b5610
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1fb5; Write addr: 0x7ff7077b5610
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1fbe; Read addr: 0x7ff7077b5618
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1fbe; Write addr: 0x7ff7077b5618
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b19e9; Write addr: 0x7ff7077b55b0
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b23d2; Read addr: 0x7ff7077b5030
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1e37; Read addr: 0x7ff7077b55b8
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1e37; Write addr: 0x7ff7077b55b8
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1a0c; Read addr: 0x7ff7077b5638
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1a38; Read addr: 0x7ff7077b5630
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b10be; Read addr: 0x7ff7077b5628
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b10c6; Write addr: 0x7ff7077b5628
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b10be; Read addr: 0x7ff7077b5628
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b10c6; Write addr: 0x7ff7077b5628
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b10be; Read addr: 0x7ff7077b5628
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b10c6; Write addr: 0x7ff7077b5628
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b10be; Read addr: 0x7ff7077b5628
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b10c6; Write addr: 0x7ff7077b5628
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b10be; Read addr: 0x7ff7077b5628
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b10c6; Write addr: 0x7ff7077b5628
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b10be; Read addr: 0x7ff7077b5628
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b10c6; Write addr: 0x7ff7077b5628
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b143d; Read addr: 0x7ff7077b5008
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1860; Read addr: 0x7ff7077b5008
local counter: 3
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b143d; Read addr: 0x7ff7077b5008
global counter: [PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1860; Read addr: 0x7ff7077b5008
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b117a; Read addr: 0x7ff7077b5628
6
[PINTOOL] Loading image: C:\WINDOWS\System32\kernel.appcore.dll; Image ID: 8
[PINTOOL] Loading image: C:\WINDOWS\System32\msvcrt.dll; Image ID: 9
[PINTOOL] Loading image: C:\WINDOWS\System32\RPCRT4.dll; Image ID: 10
[PINTOOL] Unloading image: G:\Appdata\CPP\PinTestSimpleTarget\x64\Release\PinTestSimpleTarget.exe
[PINTOOL] Unloading image: C:\WINDOWS\System32\KERNELBASE.dll
[PINTOOL] Unloading image: C:\WINDOWS\System32\KERNEL32.DLL
[PINTOOL] Unloading image: C:\WINDOWS\SYSTEM32\ntdll.dll
[PINTOOL] Unloading image: C:\WINDOWS\System32\ucrtbase.dll
[PINTOOL] Unloading image: C:\WINDOWS\SYSTEM32\VCRUNTIME140.dll
[PINTOOL] Unloading image: C:\WINDOWS\SYSTEM32\MSVCP140.dll
[PINTOOL] Unloading image: C:\WINDOWS\System32\kernel.appcore.dll
[PINTOOL] Unloading image: C:\WINDOWS\System32\msvcrt.dll
[PINTOOL] Unloading image: C:\WINDOWS\System32\RPCRT4.dll
[PINTOOL] Instrumentation tear down.

Очевидно, что есть некоторые другие глобальные переменные, используемые программой для внутренних целей;но по крайней мере это должно дать вам хорошее представление о том, как отслеживать глобальные переменные в вашей программе.

...