2011年2月15日火曜日

Stuxnet source code reading

Laurelai / decompile-dump
https://github.com/Laurelai/decompile-dump
嘘か真か、Stuxnetのソースコードらしいです。

Partial stuxnet source decompiled with boomerang, if anyone has better decompile tools feel free to contribute better versions

2011年2月14日 15:30(PST)現在で中身はこんな感じです。

./016169EBEBF1CEC2AAD6C7F0D0EE9026/016169EBEBF1CEC2AAD6C7F0D0EE9026.c
./055A3421813CAF77E1387FF77B2E2E28/055A3421813CAF77E1387FF77B2E2E28.c
./1E17D81979271CFA44D471430FE123A5/1E17D81979271CFA44D471430FE123A5.c
./30DF51C9F0D9B010350DC09ABE1E4E97/30DF51C9F0D9B010350DC09ABE1E4E97.c
./335707EABBE7FF256E0650432ACCEC9B/335707EABBE7FF256E0650432ACCEC9B.c
./37FC7C5D89F1E5A96F54318DF1A2B905/37FC7C5D89F1E5A96F54318DF1A2B905.c
./4589EF6876E9C8C05DCF4DB00A54887B/4589EF6876E9C8C05DCF4DB00A54887B.c
./74DDC49A7C121A61B8D06C03F92D0C13/74DDC49A7C121A61B8D06C03F92D0C13.c
./789F6F8DE3F140CF5D73BEF0B8ABAF78/789F6F8DE3F140CF5D73BEF0B8ABAF78.c
./7A4E2D2638A454442EFB95F23DF391A1/7A4E2D2638A454442EFB95F23DF391A1.c
./98FBEBD8883021FBE6464C37ACF17938/98FBEBD8883021FBE6464C37ACF17938.c
./a/a.c
./A3844A1B6BEA3F6FAF9C276858F40960/A3844A1B6BEA3F6FAF9C276858F40960.c
./C1CB4117D9998C79AE10C1B890C23A4D/C1CB4117D9998C79AE10C1B890C23A4D.c
./CA9EABEAB482524E5797C684398335D5/CA9EABEAB482524E5797C684398335D5.c
./CC1DB5360109DE3B857654297D262CA1/CC1DB5360109DE3B857654297D262CA1.c
./F8153747BAE8B4AE48837EE17172151E/F8153747BAE8B4AE48837EE17172151E.c
./F979C6A3E668C5073C4C6506461B034E/F979C6A3E668C5073C4C6506461B034E.c
./F9BAE53E77B31841235F698955AECE30/F9BAE53E77B31841235F698955AECE30.c
./log

ざっと見た感じ、mainあるいはWinMain関数は見当たりませんでした。代わりに789F6F8DE3F140CF5D73BEF0B8ABAF78.c と 7A4E2D2638A454442EFB95F23DF391A1.c の2つのファイルにDllMain関数があります。

7A4E2D2638A454442EFB95F23DF391A1.c

BOOL __stdcall DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
  int v3; // eax@2

  HMODULE v4; // eax@2


  sub_1000F9F2();
  if ( fdwReason == 1 )
  {
    loc_1000F9F7();
    v3 = sub_10010BBF((int)&unk_10042088);
    v4 = LoadLibraryA((LPCSTR)v3);
    sub_1000BDF5(v4);
    sub_1000F3E8();
  }
  return 1;
}

ここで呼び出している、sub_10010BBFが暗号化された構造体をほどく関数っぽい。v3に入った文字列らしきものをもとに、LoadLibraryAで外ぶらりブラリを読み込み。で、そのあと読み込んだライブラリの構造体のアドレスをdword_100420F4というグローバルな配列に突っ込んでる。

int __stdcall sub_1000BE50(int a1)
{
  return dword_100420F4[2 * a1];
}

こいつが、N番目に読み込んだライブラリの構造体を返す関数かな。



こっからはひねってあるデータの復号コード。

int __cdecl sub_10010BBF(int a1)
{
  int result; // eax@2

  if ( *(_BYTE *)(a1 + 8) )
  {
    sub_10010B9B(a1 + 11, *(_WORD *)(a1 + 9));
    *(_BYTE *)(a1 + 8) = 0;
    result = a1 + 11;
  }
  else
  {
    result = a1 + 11;
  }
  return result;
}

a1 + 8, a1 + 9, a1 + 11という3要素から、

struct {
  int a; // 0-3
  int b; // 4-7
  char c; // 8
  short d; // 9-10 : 文字数
  char e[N]; // 11- 暗号化された文字列
} 

という感じですかね。さらに追いかけると


void __cdecl sub_10010B9B(int a1, unsigned int a2)
{
  int v2; // edi@1

  v2 = 0;
  if ( a2 )
  {
    do
    {
      *(_BYTE *)(v2 + a1) -= sub_10010B6D(v2);
      ++v2;
    }
    while ( v2 < a2 );
  }
}
変換している。何文字目かによって変換規則が違う模様。
unsigned int __cdecl sub_10010B6D(int a1)
{
  int v2; // eax@1


  v2 = (a1 + 11) * (a1 + 17);
  return (a1 + 11) * (a1 + 17) ^ (((a1 + 11) * (a1 + 17) & 0xFFFFFF00 ^ ((((unsigned int)((a1 + 11) * (a1 + 17)) >> 8) ^ v2 & 0xFF0000) >> 8)) >> 8);
}

こいつが実質的なメインの関数ぽい。
char __cdecl sub_1000F3E8()
{
  char result; // al@1

  result = sub_1000F42C();
  if ( result )
  {
    result = sub_1000F405();
    if ( result )
    {
      sub_1000C37C();
      // ここでスレッドを作っている
      result = (unsigned int)sub_1000FB06(0, dwStackSize, (LPTHREAD_START_ROUTINE)StartAddress, 0, 0, 0);
    }
  }
  return result;
}

突っ込み始めるときりがない and リンクが切れているぽいところもあるので、とりあえずここまで。なんとなくの想像では、DLL読み込ませて常駐スレッドを生成するためのDLL?

0 件のコメント:

コメントを投稿