10

一部の Java .class ファイルを逆コンパイルした後に難読化を解除しようとしていますが、使用できないと思われる方法でラベルを使用しているコードの一部に出くわしました。これがラベルを誤解した逆コンパイラのせいなのか、それともコードが意図的にこのように難読化されたのかはわかりません。つまり、Java バイトコードでラベルをこのように使用できますか?

ラベルは、関連する break ステートメントの前ではなく、後に表示されることに注意してください。ラベルがループから抜け出すために使用されているのではなく、後藤としてそれらを使用しているようです。ループもまったくないので、ここでどのように使用されるのか少し混乱しています。

何が起きてる?コメントで 3 つのラベルをマークしました (###)

if (i != 96)
  {
    if ((i ^ 0xFFFFFFFF) != -98)
    {
      if (i == 98)
        break label417;  // ### Here are the three breaks... The relevant labels appear later in the code
      if (i != 99)
        break label540;
      if (!bool)
        break label461;
    }
  }
  else
  {
    if (localwb == this.localWB5)
    {
      if (this.localWB4 != null) {
          this.localWB4.a((byte)-92, this);
        if (!bool);
      }
      else
      {
          this.localWB6.a((byte)-9, this);
      }
      return true;
    }
    if (localwb == this.localWB4)
    {
        this.localWB6.a((byte)-59, this);
      return true;
    }
    if (this.localWB3 != localwb)
      break label540;
      this.localWB2.a((byte)-38, this);
    return true;
  }
  if (this.localWB6 == localwb)
  {
    if (this.localWB4 != null) {
        this.localWB4.a((byte)-122, this);
      if (!bool);
    }
    else {
        this.localWB5.a((byte)-63, this);
    }
    return true;
  }
  if (this.localWB4 == localwb)
  {
    this.localWB5.a((byte)-22, this);
    return true;
  }
  if ((this.localWB2 == localwb) && (this.localWB3.M))
  {
    this.localWB3.a((byte)-84, this);
    return true;
    label417:  //  ### The first label.  Note how this next if-statement has inaccessible code... if the above if-statement is true, it would have already returned true;  However, the label appears after the return statement, almost as if the label is being used as a goto.
    if (localwb == this.localWB2)
    {
        this.localWB6.a((byte)-86, this);
      return true;
    }
    if (this.localWB3 == localwb)
    {
      this.localWB5.a((byte)-31, this);
      return true;
      label461:  //  ###  The second label
      if ((this.localWB6 == localwb) || (this.localWB4 == localwb))
      {
          this.localWB2.a((byte)-60, this);
        return true;
      }
      if (localwb == this.localWB5)
      {
        if (this.localWB3.M)
        {
          this.localWB3.a((byte)-44, this);
          if (!bool);
        }
        else {
            this.localWB2.a((byte)-9, this);
        }
        return true;
      }
    }
  }
  label540:  //  ###  The final label.
4

4 に答える 4

5

gotoバイトコード命令(はい、実際には「goto」と呼ばれます) は、実装breakやその他の構造に使用されます。

gotoそれ自体の指定は、ターゲットが命令と同じメソッド内にあることのみgotoを制限します。

4.10classで定義されている他の多くの制約があります。Verification of Files、特にChecking Codeでは、メソッドの実際のバイトコードを検証する方法について説明しています。

たとえば、ターゲット命令がソース命令と互換性があることを要求することによって、ローカル変数とオペランドスタックの矛盾した解釈を生成することはできないと思いますが実際gotoの仕様は Prolog で記述されているため、誰もがこれが保証される適切なポイントを得ました。

于 2013-01-24T08:04:12.393 に答える
2

break <label>次のように、コード ブロックを終了するために使用できます。

public static boolean is_answer(int arg) {
    boolean ret = false;
    label: {
        if (arg != 42)
            break label;
        ret = true;
    }
    return ret;
}

ただし、表示される逆コンパイルされたコードは、次の JLS 要件により有効な Java ではありません。

ステートメントは、囲んでいるステートメントから制御breakを移します。

于 2013-01-24T07:51:07.830 に答える
2

この問題は、Java とバイトコードの不一致が原因です。Java には、バイトコード レベルには存在しない多くの制限があります。通常のコンパイル済み Java クラスファイルを逆コンパイルするだけであれば、これは問題になりません。ただし、難読化ツールは通常、メソッドの制御フローを、有効な Java にもはや対応しない同等のバージョンに再配置します。これまで見てきたように、素朴な逆コンパイラは混乱し、無効な Java を出力するだけです。

難読化されたクラスファイルの逆コンパイルに興味がある場合は、私が書いたオープン ソースのKrakatau Decompilerを試すことができます。難読化されたバイトコードを有効な Java に変換しようとするほうがはるかに賢明であるため、多くの場合、他の逆コンパイラではできないクラスを逆コンパイルできます。ただし、結果として得られるコードは、たとえそれが有効であってもおそらくきれいではなく、逆コンパイラは依然として失敗する可能性があります。

于 2013-02-01T18:31:51.913 に答える
0

Java 言語とその作成方法について質問があるときはいつでも、非常に詳細なドキュメントである便利な Java 言語仕様を参照します。

14.15breakから。声明_

break ステートメントは、すぐに囲んでいるメソッド、コンストラクター、または初期化子内のラベルを参照する必要があります。非ローカル ジャンプはありません。すぐ外側のメソッド、コンストラクター、または初期化子のラベルとして Identifier を持つラベル付きステートメントに break ステートメントが含まれていない場合、コンパイル時エラーが発生します。

ブレーク ラベルのラベルを示すものは何も表示されません。ブレークの前または「囲む」必要があります。

于 2013-01-24T07:50:51.127 に答える