A BitMessage Spam bot written by Python
BitMessage is a anonymous messaging app which uses blockchain to communicate. There is gotta be some evil things I can do with it. - 22 yo me.
Why?
Recently I been studing Blockchain and I remembered there is a messenger app called BitMessage which is used by activisms during protests a while ago. So I download it back to my laptop to see what has changed since. If you are not familar with BitMessage, it is a really cool application lives on blockchain, you can find more useful and accurate information on their wiki page.
After surfing around their Github I found that they have API built into client allows other program to communicate with the client. So, why not try to spam this specific protocol to see what blockchain can prevent with spam bot?
Let's Spam It!
Environment
First, we are going to use PyBitmessage to be our API Proxy. Basically it runs on all platforms because of Python + QT, pick whatever operation system you have and let's roll!
First of all we need to open our newly downloaded Bitmessage client and let it sync through the data. Sync is finished if you sees Object(s) to be synced = 0
, next we need to retrieve keys.dat
. Normally keys.dat
is bundled within the application. Go to Settings
-> Settings
and check the Run in Portable Mode
. After you close the application, keys.dat
should appear inside the folder.
Enable API Proxy
Use your favorite editor to open keys.dat
, add following information.
apiport = 8442
apiinterface = 127.0.0.1
apiuseranme = <desireusername>
apipassword = <desirepassword>
After that, open Bitmessage again and uncheck the Run in Portable Mode
, you can let it keep running in the background.
The Making of Spam Bot
Bitmessage API is using xmlrpc
to communicate according to API docs. We can use simple Python console to test the connection.
apiUri = "http://username:password@127.0.0.1:8442"
api = xmlrpclib.ServerProxy(apiUri)
After connection is established you can use simple add
method to check if client can start handle requests.
>>>> api.add(2,3)
5
>>>>
Retrieve Chan Addresses
To make the spam bot have most converages of users, target to Chans is the best idea. First we need to retrieve all address which I pre-added to Bitmessage. Example code will be something like below
import xmlrpclib
import json
def get_address():
client_address = json.loads(api.listAddresses())
target_address = []
y = 0
for x in client_address['addresses']:
target_address.append(client_address['addresses][y]['address'].encode('ASCII', 'ignore'))
y += 1
return target_address
if __main__ == "__name__":
apiUri = "http://username:password@127.0.0.1:8442"
api = xmlrpclib.ServerProxy(apiUri)
print get_address()
After can printed all the addresses, we need to work on the spam part.
Send Message
On official API docs send message through API is fairly easy, encode desire message to base64
and you are able to send the request to API. However, this is not a good spam bot, it require to modify hardcoded message in order to spam a new message. Proper spam bot is needed to edit message on the fly while program is running, so we need to make a text file to store messages. I make a content.txt
to store spam message.
This is title, I'm going to spam message.
This is the message body
In order to read this file, we need to write a new method.
def send_message():
with open('content.txt', 'r+') as f:
con = f.read().split('\n', 1)
subject = con[0]
content = con[1]
subject = subject.encode('utf-8').strip()
subject_data = base64.b64encode(subject)
content = content.encode('utf-8').strip()
content_data = base64.b64encode(content)
while True:
for j in addrs:
ack_data = api.sendMessage(j, j, subject_data, content_data, 2)
print 'Sent:', ackData
time.sleep(2)
print 'All address are looped, sleep 3600 seconds.'
time.sleep(3600)
return
And now you have your simple spam bot.
Polish the Code
Since the end game is distribute to cross-platform, we need to make our little spam bot able to self-generate config file and content text file.
import os
import sys
from os import path, environ
def get_config_folder():
app_folder = "PyBitmessage"
data_folder = None
if "BITMESSAGE_HOME" in environ:
data_fonder = environ["BITMESSAGE_HOME"]
if data_fonder[-1] not in [os.path.sep, os.path.altsep]:
data_folder += os.path.sep
elif sys.platform == 'darwin':
if "HOME" in environ:
data_folder = path.join(os.environ["HOME"], "Library/Application Support/", app_folder) + '/'
elif sys.platform == 'win32':
data_folder = path.join(environ["APPDATA"].decode(sys.getfilesystemencoding(), 'ignore'), app_folder) + path.sep
else:
try:
data_folder = path.join(environ["XDG_CONFIG_HOME"], app_folder)
except KeyError:
data_folder = path.join(environ["HOME"], ".config", app_folder)
return data_folder
Using method above we can retrieve keys.dat
from almost every platforms. Then we need to retrieve api config from it. To be noted keys.dat
have same format of ConfigParser
. After little copy and paste, result should somewhat like this.
import os
import sys
from os import path, environ
def get_config_folder():
app_folder = "PyBitmessage"
data_folder = None
if "BITMESSAGE_HOME" in environ:
data_fonder = environ["BITMESSAGE_HOME"]
if data_fonder[-1] not in [os.path.sep, os.path.altsep]:
data_folder += os.path.sep
elif sys.platform == 'darwin':
if "HOME" in environ:
data_folder = path.join(os.environ["HOME"], "Library/Application Support/", app_folder) + '/'
elif sys.platform == 'win32':
data_folder = path.join(environ["APPDATA"].decode(sys.getfilesystemencoding(), 'ignore'), app_folder) + path.sep
else:
try:
data_folder = path.join(environ["XDG_CONFIG_HOME"], app_folder)
except KeyError:
data_folder = path.join(environ["HOME"], ".config", app_folder)
return data_folder
def get_bm_config(setting_key):
value = None
try:
value = cp.get(settings_section, setting_key)
except Exception as e:
pass
return value
if __main__ == "__name__":
cp = ConfigParser.SafeConfigParser()
cp.read(get_config_fonder() + 'keys.dat')
After combine both config retrieve and send message code, this spam bot is ready for production.
Conclusion
I have made couple of spam bots, basically all bots does the same thing, same concept. The idea of using blockchain to deliver message is paradox, it is good to be fully anonymous when you trying to say something on the internet. However, this concept can also be easily adopt by criminals. Overall I think even though Bitmessage have come so far, there is still a long way to go.
About Bitmessage's POW (Proof-of-Work) even at this point writing this article, I have not figure it out how this system worked. I tried to browse someone elses code on send message part they are not using that method too. At first I did not think my bot will be working without doing POW before message sending out, but I do get some replies from Chans that complaining the dummy message I sent. Hence I guess this worked. :P