Можно ли переписать сегмент кода с помощью обычной программы на C ++ под Windows XP? - PullRequest
3 голосов
/ 22 ноября 2010

В настоящее время я изучаю аварийный дамп Windows, и отладчик Visual Studio показывает мне «недопустимую инструкцию 0xC000001D» при открытии файла дампа. Позиция кода, в которой показана эта ошибка, показывает разборку в следующем примере:

 void g(int x) {
 00401E80  push        ebp  
 00401E81  mov         ebp,esp 
    if(x > 20) {
 00401E83  cmp         dword ptr [x],14h 
 00401E87  jle         g+14h (401E94h) 
        x *= 4;
>00401E89  db          0fh  // illegal instruction here
 00401E8A  db          0fh  
 00401E8B  xadd        eax,esp 
 00401E8E  add         cl,byte ptr [ecx+9EB0845h] 
        x += 42;
 00401E94  mov         ecx,dword ptr [x]
 ...

Я вручную создал вышеупомянутый пример в отладчике, переписав код функции некоторыми недопустимыми значениями в окне памяти отладчиков, но аварийный дамп, который я изучаю, показывает ту же запись db 0fh, очевидно указывающую на недопустимую инструкцию. Код также похож на то, что отображает мой файл дампа, в котором все инструкции перед недопустимой инструкцией кажутся действительными и соответствуют исходному коду.

Теперь вопрос возможно ли вообще в нормально скомпилированной программе C ++ - которая не мешает ограничениям доступа к странице памяти - (Visual C ++ 2005 в Windows XP) испортить сегмент кода процесса?

Если я пытаюсь записать адрес функции в приведенном выше примере из кода, я всегда получаю нарушение прав доступа, то есть страница памяти сегмента кода выглядит защищенной от записи.

{
    void* fnAddr = &g; // non-portable but OK in VC++
    unsigned int x = 0xDEADBEEF;
    // Simulate memory corruption: Try to write something to the code segment:
    memcpy((char*)fnAddr+4, &x, sizeof(x)); // generated 0xC0000005 Access Violation
    g(42); // call messed up function - never get here
}

Известны ли вам ситуации, когда на самом деле можно было бы непреднамеренно перезаписать что-либо в сегменте кода?

Я должен добавить, что настоящая программа намного сложнее, с большим количеством виртуальных функций, некоторыми указателями на функции-члены и т. Д., И, к сожалению, проблема не воспроизводима, в настоящее время у нас есть только один файл дампа, который выглядит нормально , - Тем не менее, файл дампа отображает недопустимую инструкцию в сегменте кода, и я бы не подумал, что можно испортить сегмент кода.

Ответы [ 4 ]

3 голосов
/ 22 ноября 2010

Нет, страницы памяти, содержащие код, защищены от записи.Этот вид повреждения может произойти только во время инициализации процесса.Но более вероятный источник - мягкие ошибки ОЗУ.Попросите вашего клиента запустить программу тестирования ОЗУ.Считайте, что файл поврежден, если ошибка повторяется.

1 голос
/ 23 ноября 2010

Наиболее вероятная причина вашей сложности - переполнение локальной переменной (скажем, строки) и перезапись вашего стека. Когда подпрограмма завершается, она извлекает адрес возврата из стека и начинает выполнять любые найденные там инструкции. Этот механизм используется при атаке переполнения буфера.

1 голос
/ 22 ноября 2010

По умолчанию .text раздел имеет RX права доступа. Однако, используя VirtualProtect, вы можете получить права записи для этих страниц памяти. Но взгляните на это ..

Полагаю, это должен быть код:

code:00401000 55                                push    ebp
code:00401001 89 E5                             mov     ebp, esp
code:00401003 81 7D 08 14 00 00+                cmp     dword ptr [ebp+8], 14h
code:0040100A 7E 0B                             jle     short loc_401017
code:0040100A                   ; ---------------------------------------------------------------------------
code:0040100C 0F                                db  0Fh // here should be x += 10.5; ??
code:0040100D 0F                                db  0Fh 
code:0040100E 0F                                db  0Fh 
code:0040100F                   ; ---------------------------------------------------------------------------
code:0040100F C1 E0 02                          shl     eax, 2 ; //x *= 4
code:00401012
code:00401012                   loc_401012:
code:00401012 89 45 08                          mov     [ebp+8], eax // save x
code:00401015 EB 09                             jmp     short near ptr unk_401020
code:00401017                   ; ---------------------------------------------------------------------------
code:00401017
code:00401017                   loc_401017:                             ; CODE XREF: code:0040100Aj
code:00401017 8B 4D 08                          mov     ecx, [ebp+8]

Если я угадал коды операций, то часть отсутствует должна добавить 10,5 к eax, что не совсем возможно. Можете ли вы попытаться сделать это из любопытства

if (x > 20){
      x *= 4; 
      x += 40;
}; 

Можете ли вы также опубликовать всю функцию g(int) вместе с ее списком asm? (если возможно, с двоичными значениями кода операции, как в моем примере).

0 голосов
/ 22 ноября 2010

Да, в ситуациях, когда часть сегмента кода была сделана доступной для записи приложением, например, в JIT Java, где байт-код Java компилируется на лету в собственный код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...