0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SolidityのコードをDecompileして分析するOnline Solidity Decompilerの使い方

Last updated at Posted at 2022-02-03

公開されてないSolidityのコードを分析してみよう!

こちらの記事でEtherscanのDecompile機能を使ってみた際に、他に似たようなサービスがないかと思って、こちらのOnline Solidity Decompilerを見つけたので使い方を備忘録的に残します。

手順

こちらにコントラクトアドレスと、ネットワークを設定してDecompileをクリックします。

Screen Shot 2022-02-03 at 14.47.00.png

すると、下記のように分析結果が確認できるページが生成されます。

早速中身を見てみましょう。

分析結果の確認

Public MethodはEtherscanでは復元できていなかったgetUserNameという関数が取得できています。

Screen Shot 2022-02-03 at 14.49.13.png

また、Internal Methodも別途表示されてわかりやすいです。

Screen Shot 2022-02-03 at 14.49.19.png

Assemblyの情報も出てきます。こちらも参考情報として使えそうです。

Screen Shot 2022-02-03 at 14.51.06.png

メインとなるDecompileの結果は参考に全文記載します。

contract Contract {
    function main() {
        memory[0x40:0x60] = 0x60;
    
        if (msg.data.length < 0x04) { revert(memory[0x00:0x00]); }
    
        var var0 = msg.data[0x00:0x20] / 0x0100000000000000000000000000000000000000000000000000000000 & 0xffffffff;
    
        if (var0 == 0x1d34866f) {
            // Dispatch table entry for 0x1d34866f (unknown)
            if (msg.value) { revert(memory[0x00:0x00]); }
        
            var var1 = 0x00cd;
            var temp0 = msg.data[0x04:0x24] + 0x04;
            var temp1 = msg.data[temp0:temp0 + 0x20];
            var temp2 = memory[0x40:0x60];
            memory[0x40:0x60] = temp2 + (temp1 + 0x1f) / 0x20 * 0x20 + 0x20;
            memory[temp2:temp2 + 0x20] = temp1;
            memory[temp2 + 0x20:temp2 + 0x20 + temp1] = msg.data[temp0 + 0x20:temp0 + 0x20 + temp1];
            var var2 = temp2;
            var1 = func_02E4(var2);
            var temp3 = memory[0x40:0x60];
            memory[temp3:temp3 + 0x20] = !!var1;
            var temp4 = memory[0x40:0x60];
            return memory[temp4:temp4 + (temp3 + 0x20) - temp4];
        } else if (var0 == 0x704f1b94) {
            // Dispatch table entry for registerUser(string)
            if (msg.value) { revert(memory[0x00:0x00]); }
        
            var1 = 0x0142;
            var temp5 = msg.data[0x04:0x24] + 0x04;
            var temp6 = msg.data[temp5:temp5 + 0x20];
            var temp7 = memory[0x40:0x60];
            memory[0x40:0x60] = temp7 + (temp6 + 0x1f) / 0x20 * 0x20 + 0x20;
            memory[temp7:temp7 + 0x20] = temp6;
            memory[temp7 + 0x20:temp7 + 0x20 + temp6] = msg.data[temp5 + 0x20:temp5 + 0x20 + temp6];
            var2 = temp7;
            registerUser(var2);
            stop();
        } else if (var0 == 0xbf40fac1) {
            // Dispatch table entry for getAddress(string)
            if (msg.value) { revert(memory[0x00:0x00]); }
        
            var1 = 0x019f;
            var temp8 = msg.data[0x04:0x24] + 0x04;
            var temp9 = msg.data[temp8:temp8 + 0x20];
            var temp10 = memory[0x40:0x60];
            memory[0x40:0x60] = temp10 + (temp9 + 0x1f) / 0x20 * 0x20 + 0x20;
            memory[temp10:temp10 + 0x20] = temp9;
            memory[temp10 + 0x20:temp10 + 0x20 + temp9] = msg.data[temp8 + 0x20:temp8 + 0x20 + temp9];
            var2 = temp10;
            var1 = getAddress(var2);
            var temp11 = memory[0x40:0x60];
            memory[temp11:temp11 + 0x20] = var1 & 0xffffffffffffffffffffffffffffffffffffffff;
            var temp12 = memory[0x40:0x60];
            return memory[temp12:temp12 + (temp11 + 0x20) - temp12];
        } else if (var0 == 0xd84f55ee) {
            // Dispatch table entry for getUserName(address)
            if (msg.value) { revert(memory[0x00:0x00]); }
        
            var1 = 0x0218;
            var2 = msg.data[0x04:0x24] & 0xffffffffffffffffffffffffffffffffffffffff;
            var1 = getUserName(var2);
            var temp13 = memory[0x40:0x60];
            var2 = temp13;
            var var3 = var2;
            var temp14 = var3 + 0x20;
            memory[var3:var3 + 0x20] = temp14 - var3;
            var temp15 = var1;
            memory[temp14:temp14 + 0x20] = memory[temp15:temp15 + 0x20];
            var var4 = temp14 + 0x20;
            var var5 = temp15 + 0x20;
            var var6 = memory[temp15:temp15 + 0x20];
            var var7 = var6;
            var var8 = var4;
            var var9 = var5;
            var var10 = 0x00;
        
            if (var10 >= var7) {
            label_0258:
                var temp16 = var6;
                var4 = temp16 + var4;
                var5 = temp16 & 0x1f;
            
                if (!var5) {
                    var temp17 = memory[0x40:0x60];
                    return memory[temp17:temp17 + var4 - temp17];
                } else {
                    var temp18 = var5;
                    var temp19 = var4 - temp18;
                    memory[temp19:temp19 + 0x20] = ~(0x0100 ** (0x20 - temp18) - 0x01) & memory[temp19:temp19 + 0x20];
                    var temp20 = memory[0x40:0x60];
                    return memory[temp20:temp20 + (temp19 + 0x20) - temp20];
                }
            } else {
            label_0246:
                var temp21 = var10;
                memory[var8 + temp21:var8 + temp21 + 0x20] = memory[var9 + temp21:var9 + temp21 + 0x20];
                var10 = temp21 + 0x20;
            
                if (var10 >= var7) { goto label_0258; }
                else { goto label_0246; }
            }
        } else if (var0 == 0xed3db67c) {
            // Dispatch table entry for 0xed3db67c (unknown)
            if (msg.value) { revert(memory[0x00:0x00]); }
        
            var1 = 0x02ca;
            var2 = msg.data[0x04:0x24] & 0xffffffffffffffffffffffffffffffffffffffff;
            var1 = func_0652(var2);
            var temp22 = memory[0x40:0x60];
            memory[temp22:temp22 + 0x20] = !!var1;
            var temp23 = memory[0x40:0x60];
            return memory[temp23:temp23 + (temp22 + 0x20) - temp23];
        } else { revert(memory[0x00:0x00]); }
    }
    
    function func_02E4(var arg0) returns (var r0) {
        var var0 = 0x00;
        var var1 = var0 & 0xffffffffffffffffffffffffffffffffffffffff;
        var var2 = 0x01;
        var temp0 = arg0;
        var var3 = temp0;
        var var4 = memory[0x40:0x60];
        var var5 = var4;
        var var7 = memory[var3:var3 + 0x20];
        var var6 = var3 + 0x20;
        var var8 = var7;
        var var9 = var5;
        var var10 = var6;
    
        if (var8 < 0x20) {
        label_0335:
            var temp1 = 0x0100 ** (0x20 - var8) - 0x01;
            var temp2 = var9;
            memory[temp2:temp2 + 0x20] = (memory[var10:var10 + 0x20] & ~temp1) | (memory[temp2:temp2 + 0x20] & temp1);
            var temp3 = var7 + var5;
            memory[temp3:temp3 + 0x20] = var2;
            var temp4 = memory[0x40:0x60];
        
            if (storage[keccak256(memory[temp4:temp4 + (temp3 + 0x20) - temp4])] & 0xffffffffffffffffffffffffffffffffffffffff != var1) { return var0; }
            else { return 0x01; }
        } else {
        label_031B:
            var temp5 = var10;
            var temp6 = var9;
            memory[temp6:temp6 + 0x20] = memory[temp5:temp5 + 0x20];
            var9 = temp6 + 0x20;
            var10 = temp5 + 0x20;
            var8 = var8 - 0x20;
        
            if (var8 < 0x20) { goto label_0335; }
            else { goto label_031B; }
        }
    }
    
    function registerUser(var arg0) {
        var var0 = 0x03b8;
        var var1 = msg.sender;
        var0 = func_0652(var1);
    
        if (!var0) { revert(memory[0x00:0x00]); }
    
        var0 = 0x03cc;
        var1 = arg0;
        var0 = func_02E4(var1);
    
        if (!var0) { revert(memory[0x00:0x00]); }
    
        var temp0 = arg0;
        memory[0x00:0x20] = msg.sender;
        memory[0x20:0x40] = 0x00;
        var0 = 0x0429;
        var1 = keccak256(memory[0x00:0x40]);
        var var3 = memory[temp0:temp0 + 0x20];
        var var2 = temp0 + 0x20;
        var0 = func_0723(var1, var2, var3);
        var0 = msg.sender;
        var1 = 0x01;
        var temp1 = arg0;
        var2 = temp1;
        var3 = memory[0x40:0x60];
        var var4 = var3;
        var var6 = memory[var2:var2 + 0x20];
        var var5 = var2 + 0x20;
        var var7 = var6;
        var var8 = var4;
        var var9 = var5;
    
        if (var7 < 0x20) {
        label_0463:
            var temp2 = 0x0100 ** (0x20 - var7) - 0x01;
            var temp3 = var8;
            memory[temp3:temp3 + 0x20] = (memory[var9:var9 + 0x20] & ~temp2) | (memory[temp3:temp3 + 0x20] & temp2);
            var temp4 = var6 + var4;
            memory[temp4:temp4 + 0x20] = var1;
            var temp5 = memory[0x40:0x60];
            var temp6 = keccak256(memory[temp5:temp5 + (temp4 + 0x20) - temp5]);
            storage[temp6] = (var0 & 0xffffffffffffffffffffffffffffffffffffffff) | (storage[temp6] & ~0xffffffffffffffffffffffffffffffffffffffff);
            return;
        } else {
        label_0449:
            var temp7 = var9;
            var temp8 = var8;
            memory[temp8:temp8 + 0x20] = memory[temp7:temp7 + 0x20];
            var8 = temp8 + 0x20;
            var9 = temp7 + 0x20;
            var7 = var7 - 0x20;
        
            if (var7 < 0x20) { goto label_0463; }
            else { goto label_0449; }
        }
    }
    
    function getAddress(var arg0) returns (var r0) {
        var var0 = 0x00;
        var var1 = 0x01;
        var temp0 = arg0;
        var var2 = temp0;
        var var3 = memory[0x40:0x60];
        var var4 = var3;
        var var6 = memory[var2:var2 + 0x20];
        var var5 = var2 + 0x20;
        var var7 = var6;
        var var8 = var4;
        var var9 = var5;
    
        if (var7 < 0x20) {
        label_0511:
            var temp1 = 0x0100 ** (0x20 - var7) - 0x01;
            var temp2 = var8;
            memory[temp2:temp2 + 0x20] = (memory[var9:var9 + 0x20] & ~temp1) | (memory[temp2:temp2 + 0x20] & temp1);
            var temp3 = var6 + var4;
            memory[temp3:temp3 + 0x20] = var1;
            var temp4 = memory[0x40:0x60];
            return storage[keccak256(memory[temp4:temp4 + (temp3 + 0x20) - temp4])] & 0xffffffffffffffffffffffffffffffffffffffff;
        } else {
        label_04F7:
            var temp5 = var9;
            var temp6 = var8;
            memory[temp6:temp6 + 0x20] = memory[temp5:temp5 + 0x20];
            var8 = temp6 + 0x20;
            var9 = temp5 + 0x20;
            var7 = var7 - 0x20;
        
            if (var7 < 0x20) { goto label_0511; }
            else { goto label_04F7; }
        }
    }
    
    function getUserName(var arg0) returns (var r0) {
        var var0 = 0x0574;
        var0 = func_07A3();
        memory[0x00:0x20] = arg0 & 0xffffffffffffffffffffffffffffffffffffffff;
        memory[0x20:0x40] = 0x00;
        var temp0 = keccak256(memory[0x00:0x40]);
        var temp1 = storage[temp0];
        var temp2 = (!(temp1 & 0x01) * 0x0100 - 0x01 & temp1) / 0x02;
        var temp3 = memory[0x40:0x60];
        memory[0x40:0x60] = temp3 + (temp2 + 0x1f) / 0x20 * 0x20 + 0x20;
        var var1 = temp3;
        var var2 = temp0;
        var var3 = temp2;
        memory[var1:var1 + 0x20] = var3;
        var var4 = var1 + 0x20;
        var var5 = var2;
        var temp4 = storage[var5];
        var var6 = (!(temp4 & 0x01) * 0x0100 - 0x01 & temp4) / 0x02;
    
        if (!var6) {
        label_0646:
            return var1;
        } else if (0x1f < var6) {
            var temp5 = var4;
            var temp6 = temp5 + var6;
            var4 = temp6;
            memory[0x00:0x20] = var5;
            var temp7 = keccak256(memory[0x00:0x20]);
            memory[temp5:temp5 + 0x20] = storage[temp7];
            var5 = temp7 + 0x01;
            var6 = temp5 + 0x20;
        
            if (var4 <= var6) { goto label_063D; }
        
        label_0629:
            var temp8 = var5;
            var temp9 = var6;
            memory[temp9:temp9 + 0x20] = storage[temp8];
            var5 = temp8 + 0x01;
            var6 = temp9 + 0x20;
        
            if (var4 > var6) { goto label_0629; }
        
        label_063D:
            var temp10 = var4;
            var temp11 = temp10 + (var6 - temp10 & 0x1f);
            var6 = temp10;
            var4 = temp11;
            goto label_0646;
        } else {
            var temp12 = var4;
            memory[temp12:temp12 + 0x20] = storage[var5] / 0x0100 * 0x0100;
            var4 = temp12 + 0x20;
            var6 = var6;
            goto label_0646;
        }
    }
    
    function func_0652(var arg0) returns (var r0) {
        var var0 = 0x00;
        var temp0 = memory[0x40:0x60];
        var var1 = keccak256(memory[temp0:temp0 + memory[0x40:0x60] - temp0]);
        memory[0x00:0x20] = arg0 & 0xffffffffffffffffffffffffffffffffffffffff;
        memory[0x20:0x40] = 0x00;
        var var2 = keccak256(memory[0x00:0x40]);
        var var3 = memory[0x40:0x60];
        var var4 = var3;
        var var5 = var2;
        var temp1 = storage[var5];
        var var6 = (!(temp1 & 0x01) * 0x0100 - 0x01 & temp1) / 0x02;
    
        if (!var6) {
        label_0702:
            var temp2 = memory[0x40:0x60];
        
            if (keccak256(memory[temp2:temp2 + var4 - temp2]) != var1) { return var0; }
            else { return 0x01; }
        } else if (0x1f < var6) {
            var temp3 = var4;
            var temp4 = temp3 + var6;
            var4 = temp4;
            memory[0x00:0x20] = var5;
            var temp5 = keccak256(memory[0x00:0x20]);
            memory[temp3:temp3 + 0x20] = storage[temp5];
            var5 = temp5 + 0x01;
            var6 = temp3 + 0x20;
        
            if (var4 <= var6) { goto label_0702; }
        
        label_06EE:
            var temp6 = var5;
            var temp7 = var6;
            memory[temp7:temp7 + 0x20] = storage[temp6];
            var5 = temp6 + 0x01;
            var6 = temp7 + 0x20;
        
            if (var4 > var6) { goto label_06EE; }
            else { goto label_0702; }
        } else {
            var temp8 = var4;
            memory[temp8:temp8 + 0x20] = storage[var5] / 0x0100 * 0x0100;
            var temp9 = var6 + temp8;
            var6 = var6;
            var4 = temp9;
            goto label_0702;
        }
    }
    
    function func_0723(var arg0, var arg1, var arg2) returns (var r0) {
        var temp0 = arg0;
        var temp1 = storage[temp0];
        memory[0x00:0x20] = temp0;
        var var0 = keccak256(memory[0x00:0x20]);
        var var1 = arg1;
        arg1 = var0 + ((!(temp1 & 0x01) * 0x0100 - 0x01 & temp1) / 0x02 + 0x1f) / 0x20;
    
        if (0x1f < arg2) {
            var temp2 = arg2;
            storage[arg0] = temp2 + temp2 + 0x01;
        
            if (!temp2) {
            label_0792:
                var temp3 = arg1;
                arg1 = 0x079f;
                var0 = var0;
                arg2 = temp3;
                arg1 = func_07B7(arg2, var0);
                return arg0;
            } else {
                var temp4 = arg2;
                var temp5 = var1;
                arg2 = temp5;
                var1 = arg2 + temp4;
            
                if (var1 <= arg2) {
                label_0791:
                    goto label_0792;
                } else {
                label_077F:
                    var temp6 = arg2;
                    var temp7 = var0;
                    storage[temp7] = memory[temp6:temp6 + 0x20];
                    arg2 = temp6 + 0x20;
                    var0 = temp7 + 0x01;
                    var1 = var1;
                
                    if (var1 <= arg2) { goto label_0791; }
                    else { goto label_077F; }
                }
            }
        } else {
            var temp8 = arg2;
            storage[arg0] = temp8 + temp8 | (memory[var1:var1 + 0x20] & ~0xff);
            goto label_0792;
        }
    }
    
    function func_07A3() returns (var r0) {
        var temp0 = memory[0x40:0x60];
        memory[0x40:0x60] = temp0 + 0x20;
        memory[temp0:temp0 + 0x20] = 0x00;
        return temp0;
    }
    
    function func_07B7(var arg0, var arg1) returns (var r0) {
        var temp0 = arg0;
        arg0 = 0x07d9;
        var temp1 = arg1;
        var var0 = temp1;
        arg1 = temp0;
    
        if (arg1 <= var0) { return func_07D5(arg1, var0); }
    
    label_07C6:
        var temp2 = var0;
        storage[temp2] = 0x00;
        var0 = temp2 + 0x01;
    
        if (arg1 > var0) { goto label_07C6; }
    
        arg0 = func_07D5(arg1, var0);
        // Error: Could not resolve method call return address!
    }
    
    function func_07D5(var arg0, var arg1) returns (var r0) { return arg0; }
}

NFTやマーケットのコントラクトが公開されてない場合に分析したい、ようなケースでも使えるので、ぜひ使ってみてください!

こちらもなかなか使えそうなツールでした!また、今回のツールでsolidityのcompilerのversionも知りたいな、と思って調べていたらこちらのツールでは確認できたので、併せてどうぞ!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?