CTO TALK: Malware + Blockchain = ❤

by Sergey Potekhin, REVAIN’s CTO

This article is part of the series on writing smart contracts using the Ethereum platform. In the first piece I promised to show how to create a new crypto currency on Solidity (in the world of blockchain it is something like “Hello, world!”). But, in fact, this would make little sense as several good articles on the topic have already been published (for example, take any docs from the Solidity, or from the main page of Ethereum).

That’s why I gave it some thought and found one more “use case” for smart contracts. In this article I will show you how an author of the Trojan-encryptor can monetise his creation by selling decryption keys via smart contracts.

BTW, everything written below is for purely educational purpose.

The General Idea

Cipherers were not born yesterday and work on a more or less similar pattern. As a rule, this pattern contains the following steps:

• Redemption payment via * coin

• Sending an infected PC ID + transaction ID to criminals

• Getting the decrypting files key

So let’s try applying these three system fragments to blockchain.

General Structure of the Project

Our project consists of two parts: the administration module and the “store” module. We will conduct the admin session as a separate contract, whereas the store contract will be acquired from it. Generally speaking, in Ethereum you can interact between two different contracts in the blockchain, all you need to know are their addresses and the names of the functions you are interested in, but that I will demonstrate next time.

Tool Box

We are writing the code using Solidity version 0.4.2 (current version on October 26, 2016). As the development environment you can use the online compiler or the newly released online platform Ethereum studio. The latter is based on c9.io but also features development for Ethereum. I did not use it myself as yet since it came out only recently but it does look nice, although its creators hide the documentation on purpose.

As a client-purse let’s take Mist, and since we are doing just a PoC, we will run all contracts on our private blockchain (how to create it you can find here). So it will be easier, cheaper (of course, I meant to say free) and faster.

Writing the Code

First, create the administration module. To it we will add the function for adding and removing administrators, withdrawing money and “killing a contract.” First of all, we define all the necessary variables and the constructor function. It must be named just like the contract itself and it will be called forth only once (automatically) — when the contract is loaded into the blockchain.

pragma solidity ^0.4.2; // Указываем версию языка — любая, начиная с 0.4.2 до 0.5 не включительно

contract admin {

// VARIABLES

struct user {

address addr;

string name; // ‘$uPeR_p0wner_1999’

string desc; // ‘CEO & CTO’

}

user owner;

mapping (address => user) adminInfo;

mapping (address => bool) isAdmin;

function admin (string _name, string _desc) {

owner = user({

addr : msg.sender, // msg — дефолтная переменная с информацией о пользователе

name : _name, // вызвавшем контракт. msg.sender — его адрес

desc : _desc // msg.value — сумма в wei, переданная контракту и т.д.

});

isAdmin[msg.sender] = true;

adminInfo[msg.sender] = owner;

}

}

The code itself is simple and understandable as the syntax looks like that of C ++, JS, C, etc. Just in case let me remind you that the struct operator allows you to create custom data files from existing ones. Mapping, as you would guess, creates an associative field (dict in Python, map in C ++).

Here, with the help of struct, we create the owner variable in which we store the address, name and some description for the contract creator. Contracts in Ethereum have a so-called “state”, that means that in the future when someone calls the contract we can make use of this variable.

Next, let’s add the functions responsible for adding / removing the administrator, withdrawing money and destroying the contract. Here everything is kind of trivial, except for one thing — the operator called event. This operator in terms of UI and usability in general is very nice looking, it allows you to implement something similar to push notifications inside the contract. Below you can see a screenshot from which it is clear how it looks when it comes to practice.

// EVENTS

event adminAdded(address _address, string _name, string _desc);

event adminRemoved(address _address, string _name, string _desc);

event moneySend(address _address, uint _amount);

// FUNCTIONS

function addAdmin (address _address, string _name, string _desc) {

if (owner.addr != msg.sender || isAdmin[_address]) throw; // Только владелец может добавлять / удалять админов

isAdmin[_address] = true;

adminInfo[_address] = user({addr : _address, name : _name, desc : _desc});

adminAdded(

_address,

_name,

_desc

); // Call event

}

function removeAdmin (address _address) {

if (owner.addr != msg.sender || !isAdmin[_address]) throw;

isAdmin[_address] = false;

adminRemoved(

_address,

adminInfo[_address].name,

adminInfo[_address].desc

); // Call event

delete adminInfo[_address];

}

function getMoneyOut(address _receiver, uint _amount) {

if (owner.addr != msg.sender || _amount <= 0 || this.balance < _amount) throw;

// Функцию может вызвать только владелец, требуемая сумма должна быть положительна

// Последняя проверка — баланс контракта должен быть больше требуемой суммы

if (_receiver.send(_amount)) moneySend(_receiver, _amount); // В случае успеха — вызвать event

}

function killContract () {

if (owner.addr != msg.sender) throw;

selfdestruct(owner.addr); // Все средства на счету контракта будут переведены на адрес владельца

}

The whole code is added inside the contract admin {…} right after the already written one and our administration module is ready for action.

Filling in the Blockchain and Enjoying the Result

This step is fully described in the first part so I will not dwell on it. I’ll attach a few screenshots of the work with the contract already in use. For example, in Mist the function of adding the admin looks like:

But the promised events look like:

The Store

First, the gist: we make up a queue of already paid key applications. In our case, administrators will have to rake this heap with their own hands (you can make it automatic but again — I’ll teach you somehow next time) and add the key to the improvised database for each application (we make a map of the form _id → _key). For simplicity we make the ID a natural number and the key — string (for example, a reference to the pastebin).

The code itself fits in 85 lines and looks the following:

contract shop is admin {

// VARIABLES

uint[] orders; // Очередь из оплаченных заказов

uint currentOrder = 0; // Номер последнего необработанного заказа

mapping (uint => string) keys; // Пары ID — ключ

// EVENTS

event keyAdded(uint _ID, string _name, string _desc);

event keyBought(address _address, uint _ID);

// FUNCTIONS

function buyKey(uint _ID) payable { // Без модификатора payable на функцию нельзя отправлять эфир

if (msg.value < 15000000000000000000) throw; // Проверяем, что пользователь отправил нам минимум 15 этеров

orders.push(_ID); // Добавляем его в массив оплаченных заказов

keyBought(

msg.sender,

_ID

);

}

function getKeyByID(uint _ID) returns (string) { // Таким специфическим образом указывается, что вернет функция

return keys[_ID]; // Если ключ для этого ID еще не добавлен, то вернется пустая строка

}

function getLastOrder() returns (uint) {

if (!isAdmin[msg.sender]) throw;

return orders[currentOrder]; // Возвращаем первый ID

currentOrder += 1;

}

function addKey(uint _ID, string _key) {

if (!isAdmin[msg.sender]) throw; // Только администратор может добавить ключ для какого-то ID

keys[_ID] = _key;

keyAdded(

_ID,

adminInfo[msg.sender].name,

adminInfo[msg.sender].desc

);

}

}

Results

Let me point out once again that everything written here is a prototype with a bunch of inaccuracies and imperfections. A simple example of that is: in our case, the array of applications is not emptied and only grows in size. Because of this, someday the cost of calling the buyKey function will grow to the cost of the key itself, which is somehow not right.

Another and a more complex matter — in order to store the number of the last processed order we use the variable currentOrder. Now imagine the situation — there are two administrators: Vasya in Beijing and Petya in New York. At a certain point they turned to the getLastOrder function and both got a number, let’s say, 23412. Then each of them calls the addKey function and adds the key for this order to the “base”, and also preserved with it its name and desc. As a result, when the miners begin to perform these actions, those closer to Beijing will execute Vasya’s request faster and state will get a certain form, and those closer to New York — Petya’s and the state will look differently. As a result, this means a merge conflict.

In any case, I hope that I managed to show you what fantastic possibilities the blocking technology offers us. Even this simple contract gives hackers an opportunity to monetise malware simpler and safer, as compared to the usual schemes.

In the next article, I’ll probably write about how to fasten interfaces to contracts other than Mist (for example, interaction through an ordinary website) or how to work with Ethereum in bundled together with some programming language, for example Python. Any suggestions are gladly welcomed in the comments below.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.