Работа с InternetExplorer

Тема в разделе "WASM.BEGINNERS", создана пользователем assch, 10 авг 2020.

  1. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    192
    Сейчас многие пользуются услугами онлайн банков
    чтобы воспользоватся этой услугой нужно просто зайти по нужной ссылке на сайт
    в нужных полях прописать логин и пароль и нажать ввод
    Подобные действия хоть и немного но всё равно отнимают определённое время
    Сейчас конечно существуют мобильные приложения установленные на телефоне
    которые смогут сделать подобную операцию в автоматическом режиме
    Но всё же некоторые в том числе и я пользуются услугами онлайн банков по старинке
    Я решил хоть не много автоматизировать этот процесс авторизации
    Синтаксис проекта это Ассемблер на макросах (masm32+)
    но интуитивно я думаю здесь всё будет понятно
    Код (ASM):
    1.  
    2. ;---------------------------------------------------------------------
    3. lib shell32
    4. ;--------------------------------------------
    5. global Login "Login"
    6. global Password "Password"
    7. global Url "https://online.sberbank.ru"
    8. ;--------------------------------------------
    9. fun ShellExecute,0,"open","iexplore",&Url,0,SW_MAXIMIZE
    10. new 1024,Buffer1
    11. fun lstrcpy,Buffer1,&Login
    12. new 1024,Buffer2
    13. fun lstrcpy,Buffer2,&Password
    14. fun FunWrite
    15. ;--------------------------------------------
    16. Exit
    17. ;---------------------------------------------------------------------
    18. Fun FunWrite
    19. ;---------------------------------------------------------------------
    20. fun Sleep,1000
    21. mov eax,0
    22. ;-------------------------
    23. while eax < 2
    24. fun Sleep,10
    25. fun GetAsyncKeyState,VK_LBUTTON
    26. endw
    27. ;-------------------------
    28. fun Sleep,100
    29. fun OpenClipboard,0
    30. fun EmptyClipboard
    31. fun SetClipboardData,CF_TEXT,Buffer1
    32. fun CloseClipboard
    33. fun keybd_event,VK_CONTROL,0,0,0
    34. fun keybd_event,VK_V,0,0,0
    35. fun keybd_event,VK_CONTROL,0,KEYEVENTF_KEYUP,0
    36. fun keybd_event,VK_V,0,KEYEVENTF_KEYUP,0
    37. ;-------------------------
    38. fun Sleep,100
    39. fun keybd_event,VK_TAB,0,0,0
    40. fun keybd_event,VK_TAB,0,KEYEVENTF_KEYUP,0
    41. fun Sleep,100
    42. ;-------------------------
    43. fun OpenClipboard,0
    44. fun EmptyClipboard
    45. fun SetClipboardData,CF_TEXT,Buffer2
    46. fun CloseClipboard
    47. fun keybd_event,VK_CONTROL,0,0,0
    48. fun keybd_event,VK_V,0,0,0
    49. fun keybd_event,VK_CONTROL,0,KEYEVENTF_KEYUP,0
    50. fun keybd_event,VK_V,0,KEYEVENTF_KEYUP,0
    51. ;-------------------------
    52. fun Sleep,100
    53. fun keybd_event,VK_RETURN,0,0,0
    54. fun keybd_event,VK_RETURN,0,KEYEVENTF_KEYUP,0
    55. ;-------------------------
    56. fun Sleep,100
    57. fun OpenClipboard,0
    58. fun EmptyClipboard
    59. fun CloseClipboard
    60. ;---------------------------------------------------------------------
    61. End
    62. ;---------------------------------------------------------------------
    63. End
    64.  
    В глобальных переменных надо прописать нужные логин и пароль
    а также адрес страницы онлайн банка
    и после компиляции будет испольняемый файл
    который немного поможет избежать рутины авторизации
    Я конечно не могу поручится что эта фишка будет работать у всех
    но у меня она пока вроде бы работает
    Программа конечно не идеальная
    потому что нужно будет соблюсти одну условность
    Алгоритм работы исполняемого файла такой:

    Функция ShellExecute запускает браузер InternetExplorer
    а тот в свою очередь будет открывать страницу онлайн банка
    но так как отрытие страницы будет не быстрым
    всё зависит от того загружен InternetExplorer в оперативную память или нет
    вот тут то и нужно соблюсти одну условность
    а именно до открытия страницы не пользоватся левой кнопкой мышки
    но как только страница загрузится
    нужно в поле ввода логина (именно в поле логина)
    щёлкнуть левой кнопкой мышки и больше ничего не делать
    программа сама заполнит нужные поля и сама активирует ввод
    на этом программа закончит свою работу
    а вам нужно будет только дождатся когда откроется окно
    для ввода пароля который придёт вам на телефон

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

    И так ещё раз про алгоритм программы
    так как функция ShellExecute будет работать асинхронно
    код после неё будет отрабатыватся сразу же
    а именно создадутся два динамических буфера
    для работы с буфером обмена так как буфер обмена не хочет
    работать просто с глобальной памятью сегмента данных
    в эти буфера при помощи функции lstrcpy поместятся логин и пароль
    и начнёт работать пользовательская функция - FunWrite

    В функции сначала отработает секундная задержка
    а потом заработает цикл отслеживания
    этот цикл будет работать до тех пор пока функция - GetAsyncKeyState
    не зафиксирует в системе действие с левой кнопкой мышки
    как только это произойдёт алгоритм выйдет из цикла
    и с определёнными задержками отработают пять этапов
    -------------------------------------------
    1 - в буфер обмена загрузится логин
    программно нажмутся и отпустятся кнопки - Ctrl + V
    имитируя вставку из буфера обмена
    -------------------------------------------
    2 - программно нажмётся и отпустится кнопка - Tab
    тем самым на веб странице активирутся следующее окошко
    то есть окошко для ввода пароля
    -------------------------------------------
    3 - в буфер обмена загрузится пароль
    программно нажмутся и отпустятся кнопки - Ctrl + V
    имитируя вставку из буфера обмена
    -------------------------------------------
    4 - программно нажмётся и отпустится кнопка - Enter
    тем самым браузер отправит данные на сервер
    -------------------------------------------
    5 - буфер обмена на всякий случай
    очищаем от наших данных
    -------------------------------------------
    На этом программа заканчивает свою работу
    -------------------------------------------
    Программа намеренно открывается на весь экран
    для того чтобы пользователь не смог случайно
    кликнуть левой кнопкой мышки на других приложениях
    как только вы кликнули мышкой то можно размеры окна
    уже устанавливать любые вам удобные для работы в окне

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

    Например можно ли программно открыть браузер InternetExplorer
    с нужными размерами и например в нужном месте
    даже если для этого нужен будет батник

    Кто в курсе подскажите пожалуйста как это сделать программно

    А может кто нибудь даст дельные советы по алгоритму программы
    в плане того что это можно сделать получше

    Да вот ещё что попробывал закрыть на выходе два динамических буфера
    так программа при работе на выходе стала выдавать ошибку
    честно говоря меня это удивило
    так и пришлось оставить динамические буфера не закрытыми
    надеюсь это не страшно
    и при закрытии программы на системе это не скажется
     
  2. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.955
    На мой взгляд отличное решение вписать свой логин и пароль к сберу в текстовый файл на компе.
     
  3. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.250
    Ну кроме того, что IE уже безбожно устарел и для этого бы лучше использовать хотя бы Edge. Вообще через COM же доступен InternetExplorer.Application, который можно легко заскриптовать через интерфейс IDispatch. Ну и да, есть же Selenium, открывать окно IE и посылать ему нажатия клавиш - это как чесать правое ухо левой рукой через голову. Имхо канеш.
     
    M0rg0t нравится это.
  4. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.574
    f13nd, файл можно шифровать.

    Rel, двачую СОМ объект, и не двачую селениум.
     
  5. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    192
    Я сам не пользуюсь InternetExplorer (как наверное и многие другие)
    и по поводу того что он устарел я соответственно даже не знаю
    смею только предположить что скорее всего да чем нет
    наверное это потому что в нём нет каких нибудь навороченных плагинов
    которые несомненно в определённых моментах помогают пользователям
    Но обычный серфинг на онлайн банк я думаю он сделает не хуже других
    А вот по поводу COM это конечно интересная тема для обсуждения
    Я сам изначально сделал открытие InternetExplorer через COM
    в нём даже можно указать место и размеры открываемого окна
    Код (ASM):
    1.  
    2. ;--------------------------------------------
    3. global Web IWebBrowser2
    4. global Url u"https://online.sberbank.ru"
    5. global CLSID_InternetExplorer g"0002DF01-0000-0000-C000-000000000046"
    6. global IID_IWebBrowser2 g"D30C1661-CDAF-11D0-8A3E-00C04FC9E26E"
    7. ;--------------------------------------------
    8. new 1024,Buffer1
    9. fun lstrcpy,Buffer1,&Login
    10. ;--------------------------------------------
    11. new 1024,Buffer2
    12. fun lstrcpy,Buffer2,&Password
    13. ;--------------------------------------------
    14. fun OleInitialize,0
    15. fun CoCreateInstance,&CLSID_InternetExplorer,0,CLSCTX_LOCAL_SERVER,&IID_IWebBrowser2,&Web
    16. fun Web.put_Visible,VARIANT_TRUE
    17. fun Web.Navigate,&Url,0,0,0,0
    18. ;--------------------------------------------
    19. fun Web.put_Left,0
    20. fun Web.put_Top,0
    21. fun Web.put_Width,1000
    22. fun Web.put_Height,800
    23. fun Web.Release
    24. fun OleUninitialize
    25. ;--------------------------------------------
    26.  
    Но у подобной реализации есть один минус
    Открываемое окно имеет маленький приоритет
    и если в данный момент на месте предпологаемого открытия окна
    развёрнуто другое приложение то InternetExplorer
    откроется под ним что в данном случае не приемлемо
    Хотя может быть я что то не так сделал или не доделал
    подскажите пожалуйста
     
  6. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.250
    В MSDN написано, что у IWebBrowser2, а точнее у IWebBrowserApp, от которого первый наследуется, есть свойство HWND, что, логично предположить, является идентификатором его окна. Попробуй этот hwnd попихать во всякие функции типа SetForegroundWindow, SetWindowPos(... HWND_TOPMOST ...) и тд.
     
  7. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    192
    Большое спасибо Rel за подсказку
    Век живи век учись

    Функция - SetForegroundWindow
    тоже отлично отрабатывает
    но я думаю применение функции - SetWindowPos
    будет гораздо лучше
    Теперь не нужно определять через интерфейс положение и размеры
    а можно просто через интерфейс взять хендл окна
    и прописать эти параметры плюс z-последовательность окна
    через функцию - SetWindowPos

    Код (ASM):
    1.  
    2. fun Web.get_HWND,&hWnd
    3. fun SetWindowPos,hWnd,HWND_TOPMOST,0,0,1200,800,SWP_SHOWWINDOW
    4.  
    Параметр - HWND_TOPMOST
    конечно самый крутой но для этой реализации я думаю будет самое то

    В конце первого поста я писал
    что попробывал закрыть на выходе два динамических буфера
    но программа на выходе стала выдавать ошибку
    так и пришлось оставить динамические буфера не закрытыми

    Не в курсе почему так происходит
    что система или конкретно буфер обмена
    не хотят закрытия выделенной динамической области
     
  8. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.250
    Эмм, ты про Buffer1 и Buffer2? Ну давай начнем с того, для чего они тебе нужны в принципе, почему не достаточно их держать в секции константных данных? Потом продолжим тем, что не особо понятно, что делает макрос new конкретно? И потом еще нужно посмотреть, как ты ее освобождаешь и какая ошибка происходит? Ну и весь код, который приводит к ошибке тоже не помешает привести.
     
  9. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    192
    Я бы рад был бы прописать логин и пароль в глобальном сегменте данных
    я об этом уже писал в первом посте
    но буфер обмена почему то не хочет работать с этим сегментом
    я сам удивлён но ему подавай именно динамическую память

    А макрос - new 1024,Buffer1
    под капотом прописывает банальное выделение памяти из кучи

    Код (ASM):
    1.  
    2. .data?
    3. Buffer1 dd ?
    4. .code
    5. push 1024
    6. push 0
    7. push hHeap
    8. call HeapAlloc
    9. mov Buffer1,eax
    10.  
    и если я пропишу в конце макрос - delete Buffer1
    под капотом пропишется

    Код (ASM):
    1.  
    2. push Buffer1
    3. push 0
    4. push hHeap
    5. call HeapFree
    6.  
    программа отработает нормально
    просто на выходе выдаст ошибку

    Код исключения: c0000374
    Смещение исключения: 000ce753

    Я попробывал выделить память функцией - LocalAlloc
    с разными флагами
    программа работает без проблем
    но как только я прописывал в конце вроде бы логичное закрытие
    функцией - LocalFree
    то ещё раз повторюсь программа выполняла свою функцию
    но в конце вылетала точно такая же ошибка
     
  10. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.250
    c0000374 - это heap corruption же? Откуда в этих макросах берется hHeap? Exit что делает (ExitProcess(0) или что-то другое)?
    --- Сообщение объединено, 11 авг 2020 ---
    Ну разобраться в проблеме надо, но чисто технически в данном контексте тебе освобождать память на куче не обязательно, процесс завершится и уже как бы до этих 2048 байт на куче никакого дела нет. Вон dmd компилятор намеренно старается не освобождать память, чтобы не тратить на это время, тк обычно 2гб памяти вполне хватает, чтобы и так скомпилить подавляющее большинство программ.
    --- Сообщение объединено, 11 авг 2020 ---
    А, я похоже нашел проблему:
     
  11. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    192
    У меня в проектах под капотом в начале кода всегда прописывается
    Код (ASM):
    1.  
    2. .data?
    3. hInstance dd ?
    4. hHeap dd ?
    5. .code
    6. call GetModuleHandleA
    7. mov hInstance,eax
    8. call GetProcessHeap
    9. mov hHeap,eax
    10.  
    Отсюда и берётся это значение - hHeap
    а под капотом макроса - Exit
    банальное завершение
    Код (ASM):
    1.  
    2. push 0
    3. call ExitProcess
    4.  
    Прочитав вольный перевод я так понял
    что после вставки в буфер обмена
    система владеет объектом
    Вот по этому мне и не удалось сделать одну память
    сначала использовать её для логина а потом для пароля
    по этому и пришлось делать два объекта памяти
    и наверное по этому системе не пондравилось
    когда попытались закрыть то чем владеет она

    Может и есть какой нибудь способ забрать этот объект у системы
    Интересно было бы узнать как
    но наверное в данном случае эта реализация (овчинка выделки будет не стоить)
     
    Последнее редактирование: 11 авг 2020
  12. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.250
    Так а зачем тебе ее забирать, если система должна гарантировать, что она сама освободит эту память, когда посчитает нужным?
     
    M0rg0t нравится это.
  13. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    192
    Ещё раз большое спасибо Rel, за участие в дискусии и за ценные советы