Analysis on KickICO hack: part 1

Zhongqiang Chen
18 min readOct 20, 2019

--

Reports on KickICO hack

On July 30, 2018, the news about KickICO, a blockchain based initial coin offering platform, being hacked is the headline of many news portal, online magazines, and articles. The following is just one of them.

KickICO Platform Loses $7.7 Million in Recent Hack
https://www.bleepingcomputer.com/news/security/kickico-platform-loses-77-million-in-recent-hack/
By Catalin CimpanuJuly 30, 2018 12:15 AMOn Friday, ICO platform KickICO acknowledged a security breach during which an unknown attacker (or attackers) stole over 70 million KICK tokens ($7.7 million at the time of the hack) from the platform's wallets.According to KickICO CEO Anti Danilevski, the hack took place on Thursday, July 26, at 09:04 UTC.Platform learned of the hack from usersDanilevski says his team learned of the hack from victims who complained to the company. One victim reported that about $800,000 worth of KICK tokens suddenly went missing from his wallet.The exec says his team immediately started investigating the hack in light of the report. The investigation revealed that the intruder managed to gain access to the private key of the KickICO platform that the developers were using to manage the KICK token (also known as KickCoin) smart contract.The hacker used this key to alter the smart contract's behavior. This smart contract is how KICK tokens are traded on top of the Ethereum platform.Danilevski says the hacker destroyed KICK tokens at approximately 40 addresses and created the same amount of tokens at other 40 wallets, which were under his control.This trick didn't change the number of KICK tokens issued on the network, and hence evaded the platform's security measures put in place to analyze sudden shifts in total cryptocurrency funds available on the market.KickICO says it will refund all users"Thanks to the rapid response of our community and our coordinated team work [sic], we were able to regain control over the tokens and prevent further possible losses by replacing the compromised private key with the private key of the cold storage," Danilevski said.KickICO devs say they've regained access over the KICK smart contract and are urging users who lost funds in the hack to reach out via email at report@kickico.com."KICKICO guarantees to return all tokens to KickCoin holders. We apologize for the inconveniences," Danilevski said.

From this report, we can extract the following “facts” on the KickICO hack.

  1. The hack occurred at 09:04 UTC on July 26, 2018.
  2. The root cause for the hack is: the intruder managed to gain access to the private key of the KickICO platform that the developers were using to manage the KICK token (also known as KickCoin) smart contract.
  3. During the hack, the hacker destroyed KICK tokens at approximately 40 addresses and created the same amount of tokens at other 40 wallets, which were under his control.
  4. The KickICO team learned of the hack from victims who complained to the company.
  5. The coordinated team and the community response rapidly to the hack.
  6. The KickICO team was able to regain control over the tokens and prevent further possible losses by replacing the compromised private key with the private key of the cold storage.
  7. The unknown attacker (or attackers) stole over 70 million KICK tokens ($7.7 million at the time of the hack) from the platform's wallets.

The reaction by a regular reader toward this kind of reports and facts typically is: are these facts are accurate and how can we verify them?

This is also my immediate reaction. So, I spent a little time to analyze the KickICO hack based on publicly available information.

When did the KickICO hack actually happen?

According the report cited above, the root cause for the hack is that the intruder managed to gain access to the private key of the KickICO platform that the developers were using to manage the KICK token (also known as KickCoin) smart contract.

The smart contract for the Kick token (i.e., KickCoin) was deployed in the following transaction.

Transaction Hash: 0x3c7ba5e0f220192d28d1ea878abe18209209429214ac3feffa21d9d46b0859af
Block: 4310476 4455881 Block Confirmations
Timestamp: 753 days 4 hrs ago (Sep-25-2017 01:19:47 PM +UTC)
From: 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451
To: [Contract 0x27695e09149adc738a978e9a678f99e4c39e9eb9 Created] (KickICO: Old Token 2)
Value: 0 Ether ($0.00)
Transaction Fee: 0.077651112 Ether ($13.47)
Gas Limit: 4,100,000
Gas Used by Transaction: 3,697,672 (90.19%)
Gas Price: 0.000000021 Ether (21 Gwei)
Nonce Position 134 34
Input Data: (omitted)

This smart contract was deployed by account with address 0x5031 and the address of the smart contract is 0x2769.

The token defined by this smart contract is named “KickCoin” and the symbol of the token is “KICK” as shown by the following snippet of code from the smart contract.

contract CSToken is owned, Utils {
struct Dividend {uint256 time; uint256 tenThousandth; uint256 countComplete;}
/* Public variables of the token */
string public standard = 'Token 0.1';
string public name = 'KickCoin';
string public symbol = 'KICK';
uint8 public decimals = 8;
uint256 _totalSupply = 0;
function CSToken() {
owner = msg.sender;
// So that the index starts with 1
dividends.push(Dividend(0, 0, 0));
// 31.10.2017 09:00:00
dividends.push(Dividend(1509440400, 30, 0));
// 30.11.2017 09:00:00
dividends.push(Dividend(1512032400, 20, 0));
// 31.12.2017 09:00:00
dividends.push(Dividend(1514710800, 10, 0));
// 31.01.2018 09:00:00
dividends.push(Dividend(1517389200, 5, 0));
// 28.02.2018 09:00:00
dividends.push(Dividend(1519808400, 10, 0));
// 31.03.2018 09:00:00
dividends.push(Dividend(1522486800, 20, 0));
// 30.04.2018 09:00:00
dividends.push(Dividend(1525078800, 30, 0));
// 31.05.2018 09:00:00
dividends.push(Dividend(1527757200, 50, 0));
// 30.06.2018 09:00:00
dividends.push(Dividend(1530349200, 30, 0));
// 31.07.2018 09:00:00
dividends.push(Dividend(1533027600, 20, 0));
// 31.08.2018 09:00:00
dividends.push(Dividend(1535706000, 10, 0));
// 30.09.2018 09:00:00
dividends.push(Dividend(1538298000, 5, 0));
// 31.10.2018 09:00:00
dividends.push(Dividend(1540976400, 10, 0));
// 30.11.2018 09:00:00
dividends.push(Dividend(1543568400, 20, 0));
// 31.12.2018 09:00:00
dividends.push(Dividend(1546246800, 30, 0));
// 31.01.2019 09:00:00
dividends.push(Dividend(1548925200, 60, 0));
// 28.02.2019 09:00:00
dividends.push(Dividend(1551344400, 30, 0));
// 31.03.2019 09:00:00
dividends.push(Dividend(1554022800, 20, 0));
// 30.04.2019 09:00:00
dividends.push(Dividend(1556614800, 10, 0));
// 31.05.2019 09:00:00
dividends.push(Dividend(1559307600, 20, 0));
// 30.06.2019 09:00:00
dividends.push(Dividend(1561885200, 30, 0));
// 31.07.2019 09:00:00
dividends.push(Dividend(1564563600, 20, 0));
// 31.08.2019 09:00:00
dividends.push(Dividend(1567242000, 10, 0));
// 30.09.2019 09:00:00
dividends.push(Dividend(1569834000, 5, 0));
NewSmartToken(address(this));
}
}

In the constructor of the smart contract, the owner of the smart contract is assigned to be the sender of the transaction that created the smart contract. Therefore, account 0x5031 is the owner of the smart contract.

From the source code of the smart contract, we also know that the smart contract provides a function named changeOwner() to transfer ownership of the smart contract to a new account.

Thus, although account 0x5031 is the ownership of the smart contract when it is created, it could be changed some time during the life time of the smart contract. By analyzing all transactions associated with account 0x5031, we can ensure that account 0x5031 has not transfer its ownership of the smart contract to others, so, it is still the owner of the smart contract when the hack occurred.

The function to change ownership in the smart contract is shown below.

contract owned {
address public owner;
function owned() {
owner = msg.sender;
}
function changeOwner(address newOwner) onlyOwner {
owner = newOwner;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
}

From the reported quoted above, we know that the KickICO team learned of the hack from victims who complained to the company. That means, the KickICO team knows the hack only when they get complains from victims.

One of such complains is mentioned in the following report.

KICKICO security breach – hackers stole over $7.7 million worth of KICK tokenshttps://securityaffairs.co/wordpress/74910/hacking/kickico-hack.html
July 30, 2018 By Pierluigi Paganini

The same report also quotes the notification given by the KickICO.

“The hackers gained access to the private key of the owner of the KickCoin smart contract. In order to hide the results of their activities, they employed methods used by the KickCoin smart contract in integration with the Bancor network: hackers destroyed tokens at approximately 40 addresses and created tokens at the other 40 addresses in the corresponding amount. In result, the total number of tokens in the network has not changed. ” continues the notification.

In fact, the complain mentioned in the above report actually points to the following “suspicious” transaction that interacted with KickCoin smart contract.

Transaction Hash: 0x5a11cccc79cd9c7ab8bfba4cf118bd6582b8ab7145da7b1a2bd7d5087ed28583
Status: Success
Block: 6029623 2737566 Block Confirmations
Timestamp: 450 days 1 min ago (Jul-25-2018 09:10:35 PM +UTC)
From: 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451
To: Contract 0x27695e09149adc738a978e9a678f99e4c39e9eb9 (KickICO: Old Token 2)
Tokens Transferred:
From 0xa12431d0b9db640034b0cdfceef9cce161e62be4 To 0x27695e09149adc738a978e9a678f99e4c39e9eb9 For 3,565,329.761195 KickCoin (KICK)
Value: 0 Ether ($0.00)
Transaction Fee: 0.000318214 Ether ($0.06)
Gas Limit: 39,478
Gas Used by Transaction: 24,478 (62%)
Gas Price: 0.000000013 Ether (13 Gwei)
Nonce Position 5749 11
Input Data: Function: destroy(address _from, uint256 _amount)
MethodID: 0xa24835d1
[0]: 000000000000000000000000a12431d0b9db640034b0cdfceef9cce161e62be4
[1]: 00000000000000000000000000000000000000000000000000014443cd646ecc

This transaction was sent from account 0x5031 to contract at 0x2769. As we pointed out before, contract at 0x2769 is exactly for KickCoin token. Also, account 0x5031 is actually the owner of the smart contract for KickCoin token.

This transaction triggered the function destroy() in the smart contract for KickCoin to burn tokens, and the tokens to be destroyed come from account 0xa124. As the status of the transaction execution is “success”, the function destroy() is successfully executed and an amount of 3,565,329.761195 KickCoin (KICK) tokens did removed from account 0xa124 and returned them to the smart contract.

The source code of function destroy() in the smart contract for KickCoin is as follows.

contract CSToken is owned, Utils {
/**
* Destroy tokens
* Remove `_amount` tokens from the system irreversibly
* @param _from the address from which tokens will be burnt
* @param _amount the amount of money to burn
*/
function destroy(address _from, uint256 _amount) public {
_checkMyAging(_from);
// validate input
require((msg.sender == _from && allowManuallyBurnTokens) || msg.sender == owner);
require(accountBalance(_from) >= _amount);
balances[_from] = safeSub(balances[_from], _amount);
_totalSupply = safeSub(_totalSupply, _amount);
Transfer(_from, this, _amount);
Destruction(_amount);
}
}

It can be seen that one of the conditions required by the function destroy() is: require((msg.sender == _from && allowManuallyBurnTokens) || msg.sender == owner). Clearly, the sender of the transaction (i.e., message) is 0x5031, which is not the same as the parameter “_from” for the destroy() function. Thus, the transaction must satisfy the second condition in the statement, that is, the sender must be the owner of the smart contract.

This is another evident that 0x5031 is indeed the owner of the smart contract for the KickCoin when the hack occurs.

One important information on this transaction is that: the transaction was created on Jul-25–2018 09:10:35 PM +UTC.

Clearly, if this suspicious transaction is part of the ongoing hack, then the KickICO hack would happen much earlier than what is given in the report cited above: 09:04 UTC on July 26, 2018.

Also, the transaction pointed to by this complain may not even be the first transaction in the hack.

Thus, the hack may occur even earlier than Jul-25–2018 09:10:35 PM +UTC.

Then, when did the hack really happen?

In the second reports mentioned above, we notice that, in order to hide the results of their activities, the attackers employed methods used by the KickCoin smart contract in integration with the Bancor network. That implies at some point, the attackers may also interact with Bancor network in addition to KickCoin.

Based on this information and the analysis given above, we can simply search the history of transactions for account 0x5031 that occur around Jul-25–2018 and interact with either Bancor or KickICO. The results of the search are as follows.

Txn Hash Block Date Time (UTC) From  To Value [Txn Fee]
0xc478731d4876c0a669e83df7489c1e08a67e755f60fc96614be2db1177178093 6034847 2018-07-26 18:31:10 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT Bancor: Converter #54 0 Ether 0.000611499
0x751d5b06e5b2aba2c4725e2d427e78963511ab4ed1fd445870b781dbff3bb2c4 6034817 2018-07-26 18:24:09 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT 0x1d6835b6242d4062b99e2cca41b08ad1de059ec4 7 Ether 0.0004410x2d9fffd9151b50e5826345551fe7fa2dcd8a4c3915dc949c687ee752b00d6d9e 6029919 2018-07-25 22:21:56 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT 0xa32e9e85ae4a17bf2b9b7d275916aa1160ae215c 29 Ether 0.0002730x10efd8071d9cb076b273fd8553c0cbc7222027d7f2b2557e1daa340d69af0898 6029911 2018-07-25 22:19:52 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.0003761550x37c2de3356f42ead6d65f412e60609367309dd47f7a66de6af920a8b5315a735 6029897 2018-07-25 22:17:33 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.0013017810xc1f656a2c7defe375df6b7470249a41909646421c39772b302ed4016f137894f 6029892 2018-07-25 22:15:40 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.0003190460x6837b4898efa910a30c4dc1bcae8a4272fba198c4dcec931b3bbd7ac3be57760 6029881 2018-07-25 22:13:35 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.0013017810xf5d80f955b2fe146fef0eefb8d5ccbff3571c3c302921f51dfae3a934819cf43 6029869 2018-07-25 22:11:05 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.0013017810x3fc25517e7d3483e15515fa4a56758d21d150fae86253e4b4c48f78cb81fc86a 6029865 2018-07-25 22:09:50 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.0003190460xcc7d68c0d608036780968cb8a6c0e8663a7301842058bb31e18bf4d5de9cffb6 6029862 2018-07-25 22:07:48 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.0013017810xc236dbbff81dc8f0c390813a132a57c7d6128f8fe41bdfce71709ac634fa12fb 6029856 2018-07-25 22:06:20 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.0003190460xb2a1e8fcfbef12f8f53ef21f169b1faf56cf758f27d2dd499cd1275869f07595 6029846 2018-07-25 22:04:33 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.0013009490xfa2901e6a9b60033d2093d61f6d40d510ff2dcba0742b2917d9921c0b2e97782 6029842 2018-07-25 22:03:32 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.0003182140x9ff5f32fde6868e0e4d1382551a67afec53411418461dbbb5d2df1b715ff7f7e 6029836 2018-07-25 22:02:31 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.0013009490x324f152d5242aa397ae198b0fd62edc6370881f7a7279867670d2e68750284bf 6029830 2018-07-25 22:01:07 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.0003182140x24e68aabd7dfae7ab61ab7fa88f47647f3903ea7d233acc24d44208ba1b92971 6029822 2018-07-25 21:59:25 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.0013009490x9b394f2ce7ff0a0d652380cd0c995694917e59d65745a7014eec8eebb5d1b057 60298142018-07-25 21:57:31 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.0003182140x2b4b7215a8d3ebe3de5ffcf1cf24cfed7a6345f54ff6eaa28317b534c4deeebd 6029805 2018-07-25 21:55:43 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.0013009490x92e8593f1022ebbc6b6788afb3f6e7990db5e7d3b57ea3385003d6eb3a780058 6029794 2018-07-25 21:53:57 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.0003182140x35c6a4a973b06bc20ddab5586565e2c4a434dc7791a655024da5aaf9461c7d77 6029787 2018-07-25 21:52:12 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.0013001170xe6ab1ca74b39b1c42a64a4cd513a26dc31b40d2094b7370b71262fa333699d39 6029778 2018-07-25 21:50:57 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.000316550x26f3fee66714234ecdd1eb4a5804aa55ffc2490069a9a5b77e58a8689838e9b1 6029589 2018-07-25 21:02:09 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.000318210xac5c0fda3267d6c8705379cf682641e82a4d730a64ad36b616cf7257d2a862bf 6029583 2018-07-25 21:00:40 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.001300940x481da8d20fa0725f2535ce0f2da4d637655cef3cbd3c9a0b253845b63f73b2aa 6029577 2018-07-25 20:59:28 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.001300110xbbfff8f333b377e2e8743fd86ee2a4164e9b5da014bb41d5add699d55edbe9a3 6029561 2018-07-25 20:55:52 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.000317380x04547c5b35f48cdbf3c30c00f9ead96e3dacbf12261e74582a7fd8153b85c947 6029552 2018-07-25 20:53:45 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.000317380xc94a8fa550f11042579f7aa7d5e76c9d1c4d343e629c71a897c5e9655740b5b1 6029543 2018-07-25 20:51:33 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.000333190x791f7f95c8624c5cd4f5bf867f9012a60cb46f2a52a4140543ea277611eb864b 6029533 2018-07-25 20:49:48 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.000502550xf1f19d66521f16d456e5a3be174932a20af965b28b6f2b8b93e0a0d03898867f 6029528 2018-07-25 20:48:21 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.000318210x4e5ed084750ebbe024f20924c0575f8d254297f17184b56518ba3d280a7330ec 6029514 2018-07-25 20:45:32 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.001300940x1fd20bacaa923b4f3d1966e8b43099fd5c327cf086279dd52a2a686e7631c724 6029510 2018-07-25 20:43:35 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT KickICO: Old Token 2 0 Ether 0.000318210xac763632e265696f32db6e76513c07aac02f613a8df7f2494c6bc42a6987227f 6029499 2018-07-25 20:41:11 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451 OUT Bancor: Converter #54 0 Ether 0.00040609

From this search results, we can easily verify that the real hack happened on 2018–07–25 20:41:11 UTC at transaction 0xac76 (i.e., the transaction at the very bottom of the above information box).

Based on the above information, we can see that this transaction interacts with the Bancor converter. More specifically, this transaction is presented below.

Transaction Hash: 0xac763632e265696f32db6e76513c07aac02f613a8df7f2494c6bc42a6987227f
Status: Success
Block: 6029499 2737734 Block Confirmations
Timestamp: 450 days 38 mins ago (Jul-25-2018 08:41:11 PM +UTC)
From: 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451
To: Contract 0x51907923c3280c24b6b69b0d217ea34cabde684d (Bancor: Converter #54)
Value: 0 Ether ($0.00)
Transaction Fee: 0.000406094 Ether ($0.07)
Gas Limit: 31,300
Gas Used by Transaction: 31,238 (99.8%)
Gas Price: 0.000000013 Ether (13 Gwei)
Nonce Position 5733 21
Input Data: Function: changeTokenOwner(address _newOwner)
MethodID: 0x0f809adb
[0]: 0000000000000000000000005031129a4a1c0eaa0b98f989f9f3087c9a236451

This transaction was created on Jul-25–2018 08:41:11 PM +UTC (or 2018–07–25 20:41:11 UTC shown above). It triggered the function changeTokenOwner() in the Bancor Converter (at address 0x5190) to change the owner of the token to address 0x5031, which is the current owner of the smart contract for KickCoin.

The source code of the function changeTokenOwner() in the Bancor Converter is given blow.

/*
Smart Token interface
*/
contract ISmartToken is IOwned, IERC20Token {
function disableTransfers(bool _disable) public;
function issue(address _to, uint256 _amount) public;
function destroy(address _from, uint256 _amount) public;
}
contract SmartTokenController is TokenHolder {
ISmartToken public token; // smart token
function changeTokenOwner(address _newOwner) public ownerOnly {
token.changeOwner(_newOwner);
}
}

The function changeTokenOwner() in the Bancor Converter is quite simple, it directly calls the changeOwner() function in the token it manages to convert, which is in this case the KickCoin token.

After the successful execution of this transaction, the attackers can manipulate the token freely.

Based on the above analysis, the hack happened on 2018–07–25 20:41:11 UTC, much earlier than 2018–07–26 09:04:00 UTC given in the reports.

What did the hacker do?

According to the information given by KickICO that is revealed in the reports mentioned above, during the attack, the hacker destroyed KICK tokens at approximately 40 addresses and created the same amount of tokens at other 40 wallets, which were under his control.

The problem is: what is the exact number of addresses whose KickCoins are destroyed and how?

Let us look at the first transaction sent by the hackers after they become the owner of the KickCoin token.

Transaction Hash: 0x1fd20bacaa923b4f3d1966e8b43099fd5c327cf086279dd52a2a686e7631c724
Status: Success
Block: 6029510 2737737 Block Confirmations
Timestamp: 450 days 38 mins ago (Jul-25-2018 08:43:35 PM +UTC)
From: 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451
To: Contract 0x27695e09149adc738a978e9a678f99e4c39e9eb9 (KickICO: Old Token 2)
Tokens Transferred:
From 0x37dc04cefa0b770397cba962fbdb9162b1db8b41To 0x27695e09149adc738a978e9a678f99e4c39e9eb9For 5,407,310 KickCoin (KICK)Value: 0 Ether ($0.00)
Transaction Fee: 0.000318214 Ether ($0.06)
Gas Limit: 39,478
Gas Used by Transaction: 24,478 (62%)
Gas Price: 0.000000013 Ether (13 Gwei)
Nonce Position 5734 21
Input Data: Function: destroy(address _from, uint256 _amount)
MethodID: 0xa24835d1
[0]: 00000000000000000000000037dc04cefa0b770397cba962fbdb9162b1db8b41
[1]: 0000000000000000000000000000000000000000000000000001ebcabf2c8e00

This transaction triggers the function destroy() in the smart contract for KickCoin token to burn tokens from the given account, which is 0x37dc in this case. The total amount of tokens to be destroyed is 5,407,310 KickCoin.

This transaction was created on Jul-25-2018 08:43:35 PM +UTC, it is about 2 minutes after the attackers obtain the ownership of the token (which is on Jul-25-2018 08:41:11 PM +UTC).

Right after that, the attackers sent out another transaction shown below.

Transaction Hash: 0x4e5ed084750ebbe024f20924c0575f8d254297f17184b56518ba3d280a7330ec
Status: Success
Block: 6029514 2739441 Block Confirmations
Timestamp: 450 days 6 hrs ago (Jul-25-2018 08:45:32 PM +UTC)
From: 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451
To: Contract 0x27695e09149adc738a978e9a678f99e4c39e9eb9 (KickICO: Old Token 2)
Tokens Transferred:
From 0x27695e09149adc738a978e9a678f99e4c39e9eb9To 0x20ff0491447c6cb8e34eaa89af9747daff68aeb5For 5,407,310 KickCoin (KICK)
Value: 0 Ether ($0.00)
Transaction Fee: 0.001300949 Ether ($0.23)
Gas Limit: 100,073
Gas Used by Transaction: 100,073 (100%)
Gas Price: 0.000000013 Ether (13 Gwei)
Nonce Position 5735 66
Input Data: Function: issue(address _to, uint256 _amount)
MethodID: 0x867904b4
[0]: 00000000000000000000000020ff0491447c6cb8e34eaa89af9747daff68aeb5
[1]: 0000000000000000000000000000000000000000000000000001ebcabf2c8e00

This transaction was sent out on Jul-25–2018 08:45:32 PM +UTC, about 2 minutes after the previous transaction, which is on Jul-25–2018 08:43:35 PM +UTC.

This transaction calls the function issue() to mint tokens to the specific account, which is 0x20ff in this case. The total amount to issue is 5,407,310 KickCoin, which is exactly the same as that destroyed in the previous transaction.

Therefore, the net effect of these two transactions, one for token destroy and the other for token issuing, is that the specified amount of KickCoin has been transferred from a victim to an account controlled by the attackers, and at the same time, the total amount of tokens in the whole system remain unchanged.

This procedure, destroy tokens and then re-issue tokens, has been repeated 25 times during the entire hack process.

The final round of destroy-then-issue process is the following two transactions.

1. the destroy step:Transaction Hash: 0xc1f656a2c7defe375df6b7470249a41909646421c39772b302ed4016f137894f
Status: Success
Block: 6029892 2739270 Block Confirmations
Timestamp: 450 days 6 hrs ago (Jul-25-2018 10:15:40 PM +UTC)
From: 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451
To: Contract 0x27695e09149adc738a978e9a678f99e4c39e9eb9 (KickICO: Old Token 2)
Tokens Transferred:
From 0x8184d4ffc09369dcd5e018eefa054e6bb597aca4To 0x27695e09149adc738a978e9a678f99e4c39e9eb9For 9,680,127.69728858 KickCoin (KICK)
Value: 0 Ether ($0.00)
Transaction Fee: 0.000319046 Ether ($0.06)
Gas Limit: 39,542
Gas Used by Transaction: 24,542 (62.07%)
Gas Price: 0.000000013 Ether (13 Gwei)
Nonce Position 5784 36
Input Data: Function: destroy(address _from, uint256 _amount)
MethodID: 0xa24835d1
[0]: 0000000000000000000000008184d4ffc09369dcd5e018eefa054e6bb597aca4
[1]: 000000000000000000000000000000000000000000000000000370670947195a
2. the issue step:Transaction Hash:
0x37c2de3356f42ead6d65f412e60609367309dd47f7a66de6af920a8b5315a735
Status: Success
Block: 6029897 2739267 Block Confirmations
Timestamp: 450 days 6 hrs ago (Jul-25-2018 10:17:33 PM +UTC)
From: 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451
To: Contract 0x27695e09149adc738a978e9a678f99e4c39e9eb9 (KickICO: Old Token 2)
Tokens Transferred:
From 0x27695e09149adc738a978e9a678f99e4c39e9eb9To 0x6e808fc8786988695332f5a95721b1a5a3209ef3For 9,680,127.69728858 KickCoin (KICK)
Value: 0 Ether ($0.00)
Transaction Fee: 0.001301781 Ether ($0.23)
Gas Limit: 100,137
Gas Used by Transaction: 100,137 (100%)
Gas Price: 0.000000013 Ether (13 Gwei)
Nonce Position 5785 27
Input Data: Function: issue(address _to, uint256 _amount)
MethodID: 0x867904b4
[0]: 0000000000000000000000006e808fc8786988695332f5a95721b1a5a3209ef3
[1]: 000000000000000000000000000000000000000000000000000370670947195a

Again, the amount of KickCoin tokens that is burnt and re-issued is the same, in this case, it is 9,680,127.69728858 KickCoin.

After all these rounds of token destroying and issuing, the attackers restore the ownership of the token and switch it back to Bancor Converter, as shown in the following transaction.

Transaction Hash: 0x10efd8071d9cb076b273fd8553c0cbc7222027d7f2b2557e1daa340d69af0898
Status: Success
Block: 6029911 2739257 Block Confirmations
Timestamp: 450 days 6 hrs ago (Jul-25-2018 10:19:52 PM +UTC)
From: 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451
To: Contract 0x27695e09149adc738a978e9a678f99e4c39e9eb9 (KickICO: Old Token 2)
Value: 0 Ether ($0.00)
Transaction Fee: 0.000376155 Ether ($0.07)
Gas Limit: 28,935
Gas Used by Transaction: 28,935 (100%)
Gas Price: 0.000000013 Ether (13 Gwei)
Nonce Position 5786 52
Input Data: Function: changeOwner(address newOwner)
MethodID: 0xa6f9dae1
[0]: 00000000000000000000000051907923c3280c24b6b69b0d217ea34cabde684d

At this point, the attackers have successfully stolen KickCoin tokens and transfer them into accounts under their control. To hide their activities, the attackers also keep the total supply of token in the system unchanged. Moreover, the attackers also restore the ownership of the token to Bancor Converter.

Therefore, the total number of addresses whose tokens are destroyed by the attackers is 25, not 40.

But when did the hack really end?

Let us investigate that in the next section.

The response of KickICO

It is interesting to see that, after the attackers restore the crime scene, there are still two transactions that need our attention, which are presented below.

1. transaction ATransaction Hash: 0x2d9fffd9151b50e5826345551fe7fa2dcd8a4c3915dc949c687ee752b00d6d9e
Status: Success
Block: 6029919 2739251 Block Confirmations
Timestamp: 450 days 6 hrs ago (Jul-25-2018 10:21:56 PM +UTC)
From: 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451
To: 0xa32e9e85ae4a17bf2b9b7d275916aa1160ae215c
Value: 29 Ether ($5,044.26)
Transaction Fee: 0.000273 Ether ($0.05)
Gas Limit: 21,000
Gas Used by Transaction: 21,000 (100%)
Gas Price: 0.000000013 Ether (13 Gwei)
Nonce Position 5787 29
Input Data: 0x
2. transaction BTransaction Hash: 0x751d5b06e5b2aba2c4725e2d427e78963511ab4ed1fd445870b781dbff3bb2c4
Status: Success
Block: 6034817 2731644 Block Confirmations
Timestamp: 449 days 7 mins ago (Jul-26-2018 06:24:09 PM +UTC)
From: 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451
To: 0x1d6835b6242d4062b99e2cca41b08ad1de059ec4
Value: 7 Ether ($1,225.98)
Transaction Fee: 0.000441 Ether ($0.08)
Gas Limit: 21,000
Gas Used by Transaction: 21,000 (100%)
Gas Price: 0.000000021 Ether (21 Gwei)
Nonce Position 5788 21
Input Data: 0x

Transaction A transfers 29 Ethers from account 0x5031 to 0xa32e while transaction B transfers 7 Ethers from account 0x5031 to 0x1d68.

The questions we need to answer are: who are the actual senders of these two transactions, the attackers or the KickICO team? Are both transactions sent by the same sender: the attackers or KickICO team?

To answer these questions, let us first look at the time when these two transactions are created.

Transaction A is created on Jul-25–2018 10:21:56 PM +UTC, and transaction B is created on Jul-26–2018 06:24:09 PM +UTC. As we shown in previous section, the attackers restore the crime scene on Jul-25–2018 10:19:52 PM +UTC. So, transaction A is about 2 minutes after the transaction that restores the crime scene. In contrast, transaction B is created on Jul-26–2018 06:24:09 PM +UTC, which is more than 20 hours after the crime scene was restored by the attackers.

Based on timeline of these two transactions, we tend to consider that transaction A is sent out by the attackers, while transaction B is created by KickICO team.

Another reason for us to think transaction A belong to attackers while transaction B to KickICO team is that the setting for gas price in both transactions is different: the gas price is 13 GWei in transaction A but it is 21 GWei in transaction B. If we check all the transactions sent out by the attackers, some of which are shown above (for token destroy and issue), we can see that gas price is set to 13 GWei for all transaction created by the attackers.

If transaction B is really sent out by KickICO team, then it would be the starting point for KickICO team to try to get back control of the account 0x5031 and smart contract for KickCoin and Bancor Converter.

Let us look at the next transaction sent out from account 0x5031 to see whether or not it can give us confirmation that transaction B is indeed created by KickICO team and it acts as the start point for counter-attack.

Transaction Hash: 0xc478731d4876c0a669e83df7489c1e08a67e755f60fc96614be2db1177178093
Status: Success
Block: 6034847 2731585 Block Confirmations
Timestamp: 448 days 23 hrs ago (Jul-26-2018 06:31:10 PM +UTC)
From: 0x5031129a4a1c0eaa0b98f989f9f3087c9a236451
To: Contract 0x51907923c3280c24b6b69b0d217ea34cabde684d (Bancor: Converter #54)
Value: 0 Ether ($0.00)
Transaction Fee: 0.000611499 Ether ($0.11)
Gas Limit: 29,119
Gas Used by Transaction: 29,119 (100%)
Gas Price: 0.000000021 Ether (21 Gwei)
Nonce Position 5789 35
Input Data: Function: changeOwner(address _newOwner)
MethodID: 0xa6f9dae1
[0]: 0000000000000000000000001d6835b6242d4062b99e2cca41b08ad1de059ec4

This transaction triggers the function changeOwner() in the smart contract for KickCoin to transfer the ownership of the smart contract from 0x5031 to 0x1d68.

After the successful execution of this transaction, 0x5031 is no longer the owner of the smart contract for KickCoin token, thus, the attackers can not use this account to manipulate the KickCoin token any more. Instead, the new owner is 0x1d68 and it is the only account who can control the smart contract.

This transaction is created on Jul-26–2018 06:31:10 PM +UTC, which is about 7 minutes after transaction B is sent out, which is on Jul-26–2018 06:24:09 PM +UTC. In terms of timeline, these two transactions close to each other and are more likely created by the same sender: the KickICO team.

Also, both transactions have the same setting for gas price: 21 GWei, which is different from 13 GWei used by the attackers.

If we consider transaction A is the official end time of the hack and transaction B is the starting point for counter attack, then we can come to the following conclusions.

  1. The attack starts at Jul-25–2018 08:41:11 PM +UTC and ends at Jul-25–2018 10:21:56 PM +UTC. The duration of the attack is 1:40:45.
  2. The response of KickICO team to the attack starts at Jul-26–2018 06:24:09 PM +UTC, which is more than 20 hours after the attack ends.
  3. As an additional benefit, the attackers grab 29 Ethers from account 0x5031 after they complete the attack. It is unclear why the attackers do not drain out all the money in account 0x5031 before they leave the crime scene.
  4. The first step that KickICO team takes to get back control is to transfer the ownership of the smart contract for KickCoin to a brand new account, so that the attackers can no longer use the compromised account (i.e., 0x5031) to launch further attacks. Also, to make it unlikely for the attackers to also compromise the new owner of the smart contract, it would be best to have the new owner a complete new account, which is exactly what KickICO team did.

At this point, the new owner of the smart contract for KickCoin is 0x1d68.

The question is: is 0x1d68 really an account belonging to KickCoin team, or it turns out to be another account of the attackers?

We will look into this question and others in next part of the article.

--

--