обход антиинжекта firefox

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by sn0w, 2 Aug 2018.

  1. sn0w

    sn0w Статус пользователя:

    Joined:
    26 Jul 2005
    Messages:
    1,023
    Likes Received:
    1,297
    Reputations:
    327
    хз в реверс или сюда, как по мне - проще наверное сюда, ибо просто отладка фактически.

    давно чёто ничего не писал, сейчас у самого к фоксу тёрки, поэтому параллельно напишу.
    файрфокс свежий, 64битный.

    если кто заморачивался - наверное заметили, инжект то сделан, код внедрён, а не запускается при помощи
    CreateRemoteThread. сразу оговорюсь - это может присекать и авер своей проактивкой, которая вообщем
    тоже обходится, но это несколько приватные разработки, такчто расскажу про голый фокс просто.

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

    я использую windbg, имхо лучший дебаггер виндовый, умеет практически всё, кроме того чтобы ассемблировать
    x64 инструкции в х64 режиме, хотя х86ые в том же х64 - легко. это единственный минус. надеюсь когданибудь исправят.
    он не очень прост - но если осилить документацию, да потренироваться - лучшей альтернативы не сыскать.

    короче, вокруг да около ходить не буду, я сразу прикинул что поток попросту убивается гдето на пути следования
    от ntdll!RtlUserThreadStart и до указанной в CreateRemoteThread() LPTHREAD_START_ROUTINE. иного быть и не может
    т.к. результат отработки CreateRemoteThread успешен, а никаких сторонних шляп, которые бы могли
    вмешаться в процесс работы инжектора (а это сторонний процесс) попросту нет.

    дело в том что вообще любой юзермодный поток стартует именно с ntdll!RtlUserThreadStart, а выпиливается
    при вызове ntdll!NtTerminateThread. этим и воспользуемся.

    воспользуемся фильтрованием событий. запускаем виндбг, открываем из него файрфокс, даём команду:
    эта команда значит - брякаться когда какойто поток завершает исполнение. относится к разряду событий.
    есть кстати 2 вида причин: события отладки и программные исключения. писать долго о разнице - читайте мануалы.
    полный список можно посмотреть командой sx

    на данный момент будем часто брякаться, т.к. много потоков и одни запускаются, другие выходят итд, жмём ф5 пока
    не настанет относительное спокойствие. затем берем инжектор, который должен выполнить CreateRemoteThread,
    запускаем.. и тут мы должны брякнуться и увидеть примерно такое:

    ага. убился ктото. и скорее всего это наш поток, судя по тому что бряк произошёл сразу после инжекта.

    посмотрим его коллстек, чтобы разобраться как он сюда приполз:
    тут всё последовательно, RtlExitUserThread должна вызвать NtTerminateThread.
    а вот саму RtlExitUserThread какимто хером вызвала BaseThreadInitThunk.

    надо бы глянуть там.

    кстати вот еще. чтобы убедиться тот ли мы тред смотрим, посмотримка все командой ~
    (покажу только конец списка)

    ...
    53 Id: 5b4c.14c Suspend: 1 Teb: 000000df`7d474000 Unfrozen "URL Classifier"
    54 Id: 5b4c.2444 Suspend: 1 Teb: 000000df`7d476000 Unfrozen "Classifier Update"
    55 Id: 5b4c.249c Suspend: 1 Teb: 000000df`7d4ae000 Unfrozen
    56 Id: 5b4c.43a4 Suspend: 1 Teb: 000000df`7d4b4000 Unfrozen "StreamTrans #13"
    57 Id: 5b4c.1770 Suspend: 1 Teb: 000000df`7d47c000 Unfrozen "SaveScripts"
    58 Id: 5b4c.828 Suspend: 1 Teb: 000000df`7d47e000 Unfrozen "Cache I/O"
    59 Id: 5b4c.5a04 Suspend: 1 Teb: 000000df`7d480000 Unfrozen "mozStorage #1"
    60 Id: 5b4c.5de8 Suspend: 1 Teb: 000000df`7d482000 Unfrozen "mozStorage #2"
    61 Id: 5b4c.1c24 Suspend: 1 Teb: 000000df`7d484000 Unfrozen "mozStorage #3"
    62 Id: 5b4c.5a30 Suspend: 1 Teb: 000000df`7d4a0000 Unfrozen
    63 Id: 5b4c.5c28 Suspend: 1 Teb: 000000df`7d488000 Unfrozen "localStorage DB"
    64 Id: 5b4c.5c7c Suspend: 1 Teb: 000000df`7d48a000 Unfrozen "QuotaManager IO"
    65 Id: 5b4c.415c Suspend: 1 Teb: 000000df`7d4b6000 Unfrozen "Lazy Idle"
    . 66 Id: 5b4c.15f0 Suspend: 0 Teb: 000000df`7d4b8000 Unfrozen

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

    так вот, интересно нам с чего это BaseThreadInitThunk закинула нас самоубиваться.
    поэтому задеассемблим её:



    и тут невооружённым глазом видна какаято херня, джамп кудато в модули мозиллы. особо заморачиваться не стоит,
    т.к. уже понятно что в стандартном случае поток идёт так:

    ntdll!RtlUserThreadStart-> KERNEL32!BaseThreadInitThunk -> ...LPTHREAD_START_ROUTINE

    у нас же выходит что:

    ntdll!RtlUserThreadStart-> KERNEL32!BaseThreadInitThunk -> (offset mozglue!mozilla::Compression::LZ4::decompress+0x1b0) ->RtlExitUserThread->NtTerminateThread

    от этого можно фф отучить легко, просто поставить бряк на запись по адресу KERNEL32!BaseThreadInitThunk
    и выявить того кто пытается эту функу пропатчить. но решение на самом деле проще без всяких кряков:

    создаём замороженыйй поток (он стартует с RtlUserThreadStart но и там пока спит).
    берём его контекст, ставим RIP = LPTHREAD_START_ROUTINE, и пробуждаем. вуаля, заработало.


    Code:
           HANDLE thread = CreateRemoteThread(hndProc, NULL, 0, (LPTHREAD_START_ROUTINE) address_of_ep, NULL, CREATE_SUSPENDED, NULL);
    
           CONTEXT ctx;
           ctx.ContextFlags = CONTEXT_ALL;
           GetThreadContext(thread, &ctx);
           ctx.Rip = (DWORD64)address_of_ep;
           SetThreadContext(thread, &ctx);
           ResumeThread(thread);
           CloseHandle(thread);
    
    ну и всё. а можно попросту переписать KERNEL32!BaseThreadInitThunk в процессе фокса копией кода со своего процесса,
    тогда и без хитрости выше запашет. если конечно снова не перезапишет, не смотрел, лень. всем добра.
     
  2. DartPhoenix

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

    Joined:
    15 Sep 2013
    Messages:
    1,107
    Likes Received:
    8,482
    Reputations:
    25
    Завтречко посмотрим. Спосибо Снег. Пусть будет :)
     
  3. slesh

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

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Всё это прошлый век.
    1) Не работает инжект из 32 в 64 битные
    2) Сомневаюсь что поможет в работе во всяких EDGE где строка следят за исполнением левого кода
    3) Подобное можно засечь без проблем: в любой своей DLL в EntryPoint следить за DLL_THREAD_ATTACH и уничтожать все левые потоки.

    Если хочется универсальности и красоты, то
    1) Получаем адрес NtWaitForSingleObject
    2) Добавляем права на запись через NtProtectVirtualMemory или в случае 32->64 вызываем 64-х битный NtProtectVirtualMemory через heaven gate
    3) Пишем свой шелкод и патчим NtWaitForSingleObject для прыжка на шелкод
    4) 99% процессов в течении пару секунд вызовут шелкод и главное никакой мороки с кроссархитектурностью или любой защитой. Да и к тому же запись в память как бы менее паливное дело чем запуск удаленного потока.
     
    binarymaster and SooLFaa like this.
  4. DartPhoenix

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

    Joined:
    15 Sep 2013
    Messages:
    1,107
    Likes Received:
    8,482
    Reputations:
    25
    Но это же вроде не совсем про фаерфокс :)
    И для прыжка на шеллкод кстати это овермайнд. Я как-то тоже думал что канонишный ядырный метод переключения на процесс будет палиться. Сколько лет прошло а он не палится. Хотя может это потому что всякий это подозревает и страхуется :)
     
  5. slesh

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

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    А зачем пилить правила для процессов, когда лучше делать сразу универсально.
     
  6. DartPhoenix

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

    Joined:
    15 Sep 2013
    Messages:
    1,107
    Likes Received:
    8,482
    Reputations:
    25
    Забыл. Гуглил щас... но забыл. Была функа типа "PsGetCurrentProcess" или типа того. Не помню. И такая же функа чтобы сменить контекст.
    Я всегда хук юзал :) Думаю палевно это менять контекст такой функой :) А зря. Никто внимания не обращает.

    Но кстате Огнелис выдержит. Он патчит системные dll-ки и чуть что вываливается не объясняя причин.
     
  7. DartPhoenix

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

    Joined:
    15 Sep 2013
    Messages:
    1,107
    Likes Received:
    8,482
    Reputations:
    25
    Каждый ебется как умеет. И иногда даже барышни говорят что вот ебешься ты странно - но мне нравится :)
     
  8. DartPhoenix

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

    Joined:
    15 Sep 2013
    Messages:
    1,107
    Likes Received:
    8,482
    Reputations:
    25
    Ох чуйствую слеш щас как даст мне по жопе :)))
    Но на самом деле есть такой факт. Если ты вздумаешь его дебажить - он фокусы выкидывает с завидной регулярностью.

    А по хорошему надо бы обновить RKU.
     
  9. sn0w

    sn0w Статус пользователя:

    Joined:
    26 Jul 2005
    Messages:
    1,023
    Likes Received:
    1,297
    Reputations:
    327
    jmp 33. с подключением.
     
  10. fbidesign

    fbidesign Member

    Joined:
    13 Jul 2008
    Messages:
    79
    Likes Received:
    12
    Reputations:
    0
    Интересно. А обязательно дизасмом заниматься? Я почему-то думал что Firefox это Open Source продукт и там можно глянуть исходники... думал так, не проверял
     
  11. altblitz

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

    Joined:
    5 Jun 2009
    Messages:
    3,694
    Likes Received:
    3,149
    Reputations:
    236
    Глянь, чтож.
    И убедишься, что насыпано там немало всяких чудес,
    и в Windows, и в Linux и в Android версиях.
     
  12. sn0w

    sn0w Статус пользователя:

    Joined:
    26 Jul 2005
    Messages:
    1,023
    Likes Received:
    1,297
    Reputations:
    327
    бля да уберите этого мудака отсюда
     
  13. sn0w

    sn0w Статус пользователя:

    Joined:
    26 Jul 2005
    Messages:
    1,023
    Likes Received:
    1,297
    Reputations:
    327
    всё это хуита, ибо я заходил с заднего двора, но оказывается в исходни ках всё есть. забавно блин)
     
    DartPhoenix likes this.
  14. sn0w

    sn0w Статус пользователя:

    Joined:
    26 Jul 2005
    Messages:
    1,023
    Likes Received:
    1,297
    Reputations:
    327
    короче хуита эьто, учитывая чт о исходный код никто не скрывал оказывается, просто меня в гугле забанили
     
  15. ol1ver

    ol1ver Active Member

    Joined:
    22 Jul 2011
    Messages:
    237
    Likes Received:
    155
    Reputations:
    0
    если есть готовое решение под firefox/chrome - купил бы
     
  16. sn0w

    sn0w Статус пользователя:

    Joined:
    26 Jul 2005
    Messages:
    1,023
    Likes Received:
    1,297
    Reputations:
    327
    там покупать нечего, берешь читаешь LdrLoadDll и BaseThreadInitThunk в своём процессе и копируешь в процесс браузера. если конечно нет всяких проактивок аверских. хотя это тоже обходится со свистом, главное не шаблонить