Перехват wsock32!connect

Тема в разделе "WASM.BEGINNERS", создана пользователем Active, 27 фев 2007.

  1. Active

    Active New Member

    Публикаций:
    0
    Регистрация:
    20 фев 2007
    Сообщения:
    38
    Прошу сильно не смеяться - этот код собран из разных примеров человеком, недавно узнавшим, что такое ассемблер. Код подставляется в чужой процесс (например IE), перехватывает все попытки соединения, при каждой такой попытке должен выводить msgbox.

    Код (Text):
    1. Tread proc
    2.   Local Mhandle:HANDLE
    3.   Local RealAddr1:DWORD  
    4.   Local CurrProcID:DWORD
    5.   local Code1Addr:DWORD
    6.  
    7.  ;код перехода
    8.   call GetCurrPosition  
    9.       add ecx, 5h
    10.       jmp @F
    11.       db 68h              ; опткод push
    12.       Hooker1 dd 0
    13.       db 0c3h            ; опткод ret  
    14.    @@:      
    15.   mov Code1Addr,ecx
    16.  
    17. ;ищем функцию
    18.   dodata <db "connect",0>
    19.   push ecx
    20.   dodata <db "wsock32.dll",0>
    21.   push ecx
    22.   call EGetProcAddress
    23.   .if eax==0  
    24.        jmp Ext
    25.   .endif  
    26.    mov RealAddr1,eax  
    27.  
    28.    dodata <db "GetCurrentProcessId",0>
    29.    push ecx
    30.    dodata <db "kernel32.dll",0>
    31.    push ecx
    32.    call EGetProcAddress
    33.    
    34.    call eax
    35.    mov CurrProcID,eax
    36.  
    37. ;открываем процесс
    38.    dodata <db "OpenProcess",0>
    39.    push ecx
    40.    dodata <db "kernel32.dll",0>
    41.    push ecx
    42.    call EGetProcAddress
    43.  
    44.    push CurrProcID
    45.    push 0
    46.    push PROCESS_ALL_ACCESS
    47.    call eax  
    48.    .if eax==NULL
    49.          jmp Ext
    50.    .endif
    51.    mov Mhandle,eax
    52.  
    53.   Delt:
    54.      call GetCurrPosition
    55.      sub ecx, offset Delt
    56.      add ecx, offset Hooker  
    57.      mov eax,Code1Addr    
    58.      mov [eax+1], ecx  
    59.  
    60.              
    61.       ;записываем перехватчик
    62.       dodata <db "WriteProcessMemory",0>
    63.       push ecx
    64.       dodata <db "kernel32.dll",0>
    65.       push ecx
    66.       call EGetProcAddress
    67.      
    68.       push 0
    69.       push 6
    70.       push [Code1Addr]    
    71.       push RealAddr1
    72.       push Mhandle    
    73.       call eax  
    74.       .if eax==0
    75.           jmp Ext
    76.       .endif
    77.       ret
    78.  
    79. ; перехватчик
    80.  Hooker:
    81.    dodata <db "MessageBoxA",0>
    82.    push ecx
    83.    dodata <db "user32.dll",0>
    84.    push ecx
    85.    call EGetProcAddress
    86.    push MB_OK
    87.    dodata <db "GOTCHA!!!",0>
    88.    push ecx                          
    89.    push ecx
    90.    push 0
    91.    call eax
    92.    ret  
    93.  
    94.  Ext:  
    95.     dodata <db "ExitThread",0>
    96.     push ecx
    97.     dodata <db "kernel32.dll",0>
    98.     push ecx
    99.     call EGetProcAddress
    100.    
    101.     push 0
    102.     call eax  
    103.     ret    
    104. Tread endp
    105.  
    106. GetCurrPosition proc
    107. mov ecx, [esp]
    108. ret
    109. GetCurrPosition endp
    Здесь EGetProcAddress - процедура поиска адресов API.
    dodata - макрос вида:
    Код (Text):
    1. dodata MACRO some_data
    2.     call GetCurrPosition  
    3.     add ecx, 5h
    4.     jmp @F
    5.     &some_data
    6.     @@:            
    7.  ENDM
    Проблема в том, что код перехода не работает. То есть адрес целевой функции находится, в первые ее 6 байт что-то записывается, но не переход - при попытке использования wsock32.dll!connect программа-жертва просто падает. Кому не трудно, помогите найти ошибку - я уже голову об клаву разбил. Про необходимость приостановки потоков и восстановления оригинального начала функции я помню, но это потом.
     
  2. censored

    censored New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2005
    Сообщения:
    1.615
    Адрес:
    деревня "Анонимные Прокси"
    а почему бы за место dodata не делать проще?
    Код (Text):
    1. call skip
    2. db 'my_data', 0
    3. skip:
     
  3. Active

    Active New Member

    Публикаций:
    0
    Регистрация:
    20 фев 2007
    Сообщения:
    38
    Возможно, хотя тогда неизвестно смещение переменной. Но главное - почему не работает код перехода? Ведь все вроде правельно. Хотя какое там правельно...
     
  4. censored

    censored New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2005
    Сообщения:
    1.615
    Адрес:
    деревня "Анонимные Прокси"
    неправда, оно находится в [esp]:
    Код (Text):
    1. call skip
    2. db 'USER32.DLL', 0
    3. skip: call LoadLibrary
    P.S. код смотреть лень
     
  5. Active

    Active New Member

    Публикаций:
    0
    Регистрация:
    20 фев 2007
    Сообщения:
    38
    Черт.....хоть кто-нибудь хоть какую-нибудь мысль - я в отчаянии...
     
  6. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    "jmp @F" - точно 5 байт?
     
  7. Active

    Active New Member

    Публикаций:
    0
    Регистрация:
    20 фев 2007
    Сообщения:
    38
    Точно - по крайней мере в ecx остается верный адрес - в макросе та же технология и для всех переменных, объявленных через него, возвращается верный адрес.
    Сам код перехода
    db 68h ; опткод push
    Hooker1 dd 0
    db 0c3h ; опткод ret
    весит 6 байт.
     
  8. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    может под дебаггером посмотреть?
    ставишь перед db 68h, int3, и ловишь Just-In-Time Debugger'om.
     
  9. Active

    Active New Member

    Публикаций:
    0
    Регистрация:
    20 фев 2007
    Сообщения:
    38
    Пробовал в Olly - уходит куда-то далеко, если честно - не смог разобраться
     
  10. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    выложил бы сорц аттачем полностью. Я так гляжу, это фасм, так что я может посмотрел бы.
     
  11. Active

    Active New Member

    Публикаций:
    0
    Регистрация:
    20 фев 2007
    Сообщения:
    38
    Вот, тока это masm. Там много моего мусора и недоделок - не обращай внимание. Основная идея взята отсюда и из статей Bill'а Prisoner'а
     
  12. Active

    Active New Member

    Публикаций:
    0
    Регистрация:
    20 фев 2007
    Сообщения:
    38
    Черт, размер наверно не проходит. Придется поменьше - минимум включаемых файлов.
     
  13. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    //оффтоп
    такой код, кстати, отлаживать довольно противно (хотя метод, бесспорно, самый удобный). думаешь, что вызов какой-нить подпрограммы, а там оказывается продолжение тела текущей :)
     
  14. MSoft

    MSoft New Member

    Публикаций:
    0
    Регистрация:
    16 дек 2006
    Сообщения:
    2.854
    Во-первых, ты с дельтой че-то намудрил. Метку Delt нужно на строчку ниже опустить. Блин, у тебя и правда сложный для понимания код. И зачем после этой метки ты заполняешь локальную переменную Hooker1Addr??? Ты же ее нигде потом не используешь. Может тебе нужна переменная просто Hooker1? Только не забудь, что когда будешь заполнять hooker1, тебе надо тоже вычислить ее адрес.

    P.S.: извиняюсь, если сморозил глупость - может я где-то неправильно понял код. Просто в 2 часа ночи такой код плохо воспринимается :)

    P.P.S.: разреши дать совет: используй классический код для дельты:
    Код (Text):
    1. call delta
    2. delta:
    3. pop ebx
    4. sub ebx,delta
    Так тебе не придется каждый раз ее непонятным образом вычислять. При этом регистр ebp свободен (т.е. можешь использовать лок. переменные), а ebx
     
  15. MSoft

    MSoft New Member

    Публикаций:
    0
    Регистрация:
    16 дек 2006
    Сообщения:
    2.854
    Во-первых, ты с дельтой че-то намудрил. Метку Delt нужно на строчку ниже опустить. Блин, у тебя и правда сложный для понимания код. И зачем после этой метки ты заполняешь локальную переменную Hooker1Addr??? Ты же ее нигде потом не используешь. Может тебе нужна переменная просто Hooker1? Только не забудь, что когда будешь заполнять hooker1, тебе надо тоже вычислить ее адрес.

    P.S.: извиняюсь, если сморозил глупость - может я где-то неправильно понял код. Просто в 2 часа ночи такой код плохо воспринимается :)

    P.P.S.: разреши дать совет: используй классический код для дельты:
    Код (Text):
    1. call delta
    2. delta:
    3. pop ebx
    4. sub ebx,delta
    Так тебе не придется каждый раз ее непонятным образом вычислять. При этом регистр ebp свободен (т.е. можешь использовать лок. переменные), а ebx кроме как для дельты тебе особо и не нужен
     
  16. Active

    Active New Member

    Публикаций:
    0
    Регистрация:
    20 фев 2007
    Сообщения:
    38
    УРРА!!! Заработало =)
    Огромное спасибо. То, что в это время кто-то может заниматься моей проблемой, я и предположить не мог.
    Чемпион по глупостям здесь я - до сих пор не могу разобраться в трети того, что содрал с примеров=)
    Еще раз большое спасибо.
     
  17. Active

    Active New Member

    Публикаций:
    0
    Регистрация:
    20 фев 2007
    Сообщения:
    38
    В продолжение темы - допустим нам вместо вместо msgbox в перехватчике нужно установить свое (подменить) соединение. Порядок выполнения ясен: восстанавливаем оригинальное начало connect, вызываем ее со своими параметрами. Вопрос: к моменту попадания в перехватчик где будут находиться оригинальные параметры, переданные функции? То есть ясно, что в стеке. Можно ли их вытащить по типу pop eax прямо в перехватчике, или это совсем глупо?
     
  18. MSoft

    MSoft New Member

    Публикаций:
    0
    Регистрация:
    16 дек 2006
    Сообщения:
    2.854
    Да, это можно, но не удобно, т.к. тебе надо сначала убрать стековый кадр, потом достать адрес возврата, потом только попить параметры. Я делаю у себя так: объявляю по нормальному ф-ю обработчика

    Код (Text):
    1. MyHook proc p1,p2,...pn:DWORD
    2. some code
    3. MyHook endp
    При этом я просто заново пушу в стек переданные параметры и вызываю оригинальный обработчик, предварительно "восстановив первые байты"
     
  19. Active

    Active New Member

    Публикаций:
    0
    Регистрация:
    20 фев 2007
    Сообщения:
    38
    То есть при вызове такого обработчика без лишних движений можно будет просто pop'ить параметры, которые в свою очередь сами передадутся в стек перехватчика?

    И для интереса, если идти трудным путем "надо сначала убрать стековый кадр, потом достать адрес возврата" - адрес возврата, как я понимаю будет в [esp], но механизм работы со стеком в данном случае мне не понятен, как понять "убрать стековый кадр"?
     
  20. MSoft

    MSoft New Member

    Публикаций:
    0
    Регистрация:
    16 дек 2006
    Сообщения:
    2.854
    Нет. Если объявить перехватчик так, как написал я, то можно оперировать просто параметрами p1... Т.е. не надо будет писать что-то типа mov eax,[esp+7*4+8+...]. Тебе для вызова оригинального обработчика надо будет сделать так:
    push pn
    ...
    push p2
    push p1
    call original_func ;(только первые байты восстанови)

    Никаких попов не надо! Из своего обработчика выходишь просто с пом. ret.

    Если ты объявляешь процедуру так, как я сказал и/или используешь локальные переменные, то компилятор (во всяком случае масм) вначале прецедуры пишет push ebp/mov ebp,esp/sub esp... - это типа и есть стековый кадр. Я ж тебе и советую объявлять функию обработчика отдельно - так гораздо удобнее - и к параметрам, и к локальным переменным обращаться. Да и вообще со стеком не запутаешься. Но это только на мой взгляд.