Проблема с выделением памяти в заинжекченом процессе

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by razzzar, 19 Nov 2007.

  1. razzzar

    razzzar Elder - Старейшина

    Joined:
    16 Jun 2007
    Messages:
    92
    Likes Received:
    75
    Reputations:
    5
    Есть программа, которая инжектирует свой код в svchost.exe
    Выполняет в нем какой-то код, а потом выполняет действия наподобии этих:
    Code:
    char * szData = (char *) malloc(GetFileSize(hFile, NULL));
    ...
    free(szData);
    
    Так вот работает все отлично, но как только доходит до выделения памяти выкидует сообщение о ошибке и просьбе отослать отчет в Microsoft. Кто знает с чем связано?
     
  2. ZaCo

    ZaCo Banned

    Joined:
    20 Jun 2005
    Messages:
    737
    Likes Received:
    336
    Reputations:
    215
    >>Есть программа, которая инжектирует свой код в svchost.exe

    ну да, код может и инжекцируется, но вы уверенны, что хэндл hFile имеет место быть в процессе svchost? если нет, то malloc'у передастся -1. не хочется разбираться почему, но malloc возвращает не NULL на -1, однако очевидно, что память такого размера выделиться не может и первые четыре байта до возвращаемого указателя совсем не размер содержат...
     
    1 person likes this.
  3. KEZ

    KEZ Ненасытный школьник

    Joined:
    18 May 2005
    Messages:
    1,604
    Likes Received:
    754
    Reputations:
    397
    Гыыы) Дело в CRT-шных malloc'ах и free'хах))

    Code:
    void *new_malloc(size_t size)
    {
      return HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
    }
    
    void new_free(void *p)
    {
      HeapFree(GetProcessHeap(),0,p);
    }
    
    при инжекте в процесс многие ф-ие CRT использовать не получится

    а вообще, автор, отладчики ведь придумали не просто так

    PS
    HeapAlloc, HeapFree - это в NT на самом деле экспорт-форвардинг на ntdll.RtlAllocateHeap и соотв. ntdll.RtlFreeHeap.
    как и getlasterror=RtlGetLastWin32Error
     
    #3 KEZ, 19 Nov 2007
    Last edited: 19 Nov 2007
    4 people like this.
  4. ZaCo

    ZaCo Banned

    Joined:
    20 Jun 2005
    Messages:
    737
    Likes Received:
    336
    Reputations:
    215
    2KEZ а что в реализации этих crt-функций такого?)
     
    1 person likes this.
  5. _Great_

    _Great_ Elder - Старейшина

    Joined:
    27 Dec 2005
    Messages:
    2,032
    Likes Received:
    1,119
    Reputations:
    1,139
    Да, и очень жаль, что люди, подобные ТС, не умеют ими пользоваться.
     
    1 person likes this.
  6. DWORD

    DWORD Elder - Старейшина

    Joined:
    24 Jul 2007
    Messages:
    129
    Likes Received:
    70
    Reputations:
    -36
    Их нет как я понимаю, хотя я в отладчик не заглядывал.
     
  7. razzzar

    razzzar Elder - Старейшина

    Joined:
    16 Jun 2007
    Messages:
    92
    Likes Received:
    75
    Reputations:
    5
    спасибо за ответ )
     
  8. KEZ

    KEZ Ненасытный школьник

    Joined:
    18 May 2005
    Messages:
    1,604
    Likes Received:
    754
    Reputations:
    397
    Зако тоже не любит отладченки походу.
    Для чего нужна инициализация CRT? Вот оно инициализивалась, особенно куча тек. процесса получилась, и тут вдруг кусок кода идет в совсем другой процесс со своей кучей. Подробнее - см. дизасм malloc() и free().
    Это примерно тоже, что получить хендлы, справедливые только в текущем процессе (открытые объекты "файл", к примеру) и инжектнуть код, с ними работающий, в другой процесс, удивляясь, почему не работает.
    А в crt как бы нет ориентировки на то, что её будут хакеры использовать в целях инжекта в бедный svchost
     
    #8 KEZ, 20 Nov 2007
    Last edited: 20 Nov 2007
    1 person likes this.
  9. ZaCo

    ZaCo Banned

    Joined:
    20 Jun 2005
    Messages:
    737
    Likes Received:
    336
    Reputations:
    215
    2KEZ ну это ясно. только не понятно зачем ты щас конретизируешь кучу, ведь изначально ошибко кроется в том, что нельзя инжектить код, который использует "родные" адреса для вызова дальних jmp или call. ну в общем-то да, вот только тогда не понятно как автор решил инжектить код со своими адресами.. ахх, если бы винду собирали с crt автору при удачном стечении обстоятельств было бы попроще:)
     
    1 person likes this.
  10. KEZ

    KEZ Ненасытный школьник

    Joined:
    18 May 2005
    Messages:
    1,604
    Likes Received:
    754
    Reputations:
    397
    Все адреса при инжекте остались родными) В svchost выделили нужные адреса, скопировали туда свой образ целиком (автор, я телепат??) и запустили нужную ф-ию.
    Проблема не в jmp или call. С джампами и колами - это другая проблема, их надо релочить. А тут - косяк чисто в CRT. Достаточно посмотреть шаги работы malloc().
    Помниться, когда я только узнал про инжект в процесс, у меня была точно такая же проблема.

    хз почему ты так решил
     
    #10 KEZ, 20 Nov 2007
    Last edited: 20 Nov 2007
  11. ZaCo

    ZaCo Banned

    Joined:
    20 Jun 2005
    Messages:
    737
    Likes Received:
    336
    Reputations:
    215
    >>В svchost выделили нужные адреса

    >>Так вот работает все отлично, но как только доходит до выделения памяти выкидует
    >>сообщение о ошибке и просьбе отослать отчет в Microsoft.

    не знаю, имхо код был просто скопирован :eek:
     
  12. razzzar

    razzzar Elder - Старейшина

    Joined:
    16 Jun 2007
    Messages:
    92
    Likes Received:
    75
    Reputations:
    5
    ничего там скопированого не было. все писал я.

    2КЕЗ, да, вы телепат )
     
  13. ZaCo

    ZaCo Banned

    Joined:
    20 Jun 2005
    Messages:
    737
    Likes Received:
    336
    Reputations:
    215
    >>ничего там скопированого не было. все писал я.
    я про код процесса, а не программы на C)
     
  14. KEZ

    KEZ Ненасытный школьник

    Joined:
    18 May 2005
    Messages:
    1,604
    Likes Received:
    754
    Reputations:
    397
    > не знаю, имхо код был просто скопирован

    При инжекте у ТС с текущего процесса в адресное пространство другого по _одинаковым_ адресам копируется какой-либо код/+данные/+етц
    иначе все слетело бы ещё задолго до вызова malloc()
    о чем тут спорить можно ? : DDD
     
  15. DWORD

    DWORD Elder - Старейшина

    Joined:
    24 Jul 2007
    Messages:
    129
    Likes Received:
    70
    Reputations:
    -36
    Почему, есть инструкция call, адресующая функцию относительно текущего EIP, она кстати и используется, данные все можно формировать на стеке, api функции подключать в ходе выполнения...
     
  16. KEZ

    KEZ Ненасытный школьник

    Joined:
    18 May 2005
    Messages:
    1,604
    Likes Received:
    754
    Reputations:
    397
    Не от EIP, а от своего месторасположения.

    что тут написано и как это относится к бедному razzzar, которому уже все давно объяснили - я пока ещё не понял

    есть большой кусок кода, сгенерированый компилятором, который при перемещении в другой процесс надо либо релочить, либо перемещать на тот же VA, где он и должен быть в процессе, либо записывать его VA-независимым, например, вместо call [addr] делать mov eax,[addr]\call eax.
    тут, вроде как, неочем спорить больше.
     
  17. DWORD

    DWORD Elder - Старейшина

    Joined:
    24 Jul 2007
    Messages:
    129
    Likes Received:
    70
    Reputations:
    -36
    "от своего месторасположения" это как? 0xE8 опкод инструкции вызова функции, адрес функции вычисляется как EIP + операнд.


    Ну а почему именно такие варианты? Что мешает не использовать абсолютных адресов, формируя все данные на стеке (а глобальные переменные вынося в динамиечкую память, выделяемую уже в контексте "проинжектинного" процесса, подгружая все системные функции на лету и прыгая с функции на функцию 0xE8 call'ами (или вообще не прыгая, а делать все в __inline)
     
    #17 DWORD, 20 Nov 2007
    Last edited: 20 Nov 2007
  18. KEZ

    KEZ Ненасытный школьник

    Joined:
    18 May 2005
    Messages:
    1,604
    Likes Received:
    754
    Reputations:
    397
    Это так, что можно вычислять как EIP+операнд в момент выполнения CALL, а можно - в общем случае - адрес инструкции CALL + её операнд. Так как заранее известно, каким будет EIP в момент выполнения инструкции (когда она где-то расположена в виртуальной памяти) - думаю, уж можно сказать, что адрес процедуры будет равен адресу инструкции CALL + её операнду. Да, процессору все равно что и где там расположено, но с точки зрения чисто-человеческой логики, можно сказать про адрес инструкции call, а не про EIP в момент её выполнения, который, по сути, является тем же самым. Ладно, ок, от EIP зависит - это правильно.

    ну и?)) e8 call то должен быть расположен либо там, где и был, либо его надо корректировать. это и есть "использование абсолютных адресов"

    Компилятор мешает. Я уже сказал, что можно использовать базонезависимый код - ты как раз и говоришь про такой. Который будет где угодно выполняться. Да, да, это формирование в стеке, глобальные данные в куче, может быть замена call mem на mov reg,mem\call reg и т.п. неудобства.
    Как видно по первому посту в топике - компилятор c/cpp.
    Вот он, к примеру, очень часто будет ставить свои __CRT_CheckESP и тому подобное.
    И ещё много чего делать будет. Про __inline - без комментариев, это явно тут "ни приштопай ни пришей".
    А так, если самому писать код - да без проблем, можно полно всего придумать.
     
    #18 KEZ, 21 Nov 2007
    Last edited: 21 Nov 2007
  19. DWORD

    DWORD Elder - Старейшина

    Joined:
    24 Jul 2007
    Messages:
    129
    Likes Received:
    70
    Reputations:
    -36
    Этого я так и не понял, почему? В непосредственном операнде стоит только смещение и ему глубоко фиолетово какой там EIP, если код весь копировать монолитно, что видимо является единственно-адекватным решением, все будет работать по любым адресам.

    Кстати, чтобы call'ы имели такой вид, на сколько я понял, извращаться ненужно, я, например, смог получить call по абсолютному адресу только для 0xFF call'а при вызове функции через функциональную переменную (Borland C++), но что-то мне подсказывает что на MSVS тоже самое.
     
  20. KEZ

    KEZ Ненасытный школьник

    Joined:
    18 May 2005
    Messages:
    1,604
    Likes Received:
    754
    Reputations:
    397
    > Этого я так и не понял, почему?

    А релоки в длл придумали просто так?
    Проблема в том, что каким-то инструкциям нужна VA, а каким-то - смещение, относительно EIP. Поэтому - либо релочишь колы и джампы, либо mov'ы и все остальное.
    Как у тебя CRT инициализируется с таким кодом:

    ?

    где _osplatform == 0x42AF20

    перенесешь код - будет уже совсем неправильный адрес.