• [buuctf.reverse] 126-130


    目录

    126_[NPUCTF2020]EzObfus-Chapter2

    128_[GKCTF 2021]app-debug

    129_[FlareOn2]YUSoMeta

    130_[GXYCTF2019]minecraft


    126_[NPUCTF2020]EzObfus-Chapter2

    程序先对输入的每个字符作个处理sub_41644A()(逐字符)然后再作个逐字符的位处理,然后比对,这个符合爆破的特征

    1. int __cdecl main(int argc, const char **argv, const char **envp)
    2. {
    3. int j; // [esp+18h] [ebp-10h]
    4. int i; // [esp+1Ch] [ebp-Ch]
    5. sub_416F80();
    6. puts("Give Me Your Flag:\n");
    7. scanf("%s", &Str);
    8. if ( strlen(&Str) == 22 )
    9. {
    10. sub_41644A(); // str:0x426020 套函数里对(22个字符+i)^i 13-14除外
    11. for ( i = 1; i <= 21; ++i )
    12. {
    13. *(&Str + i) += (dword_424080[i % 6] >> 6) ^ (16 * dword_424080[(i - 1) % 6]);
    14. *(&Str + i) = ((int)(unsigned __int8)*(&Str + i) >> 3) | (32 * *(&Str + i));
    15. }
    16. for ( j = 0; j <= 21; ++j )
    17. {
    18. if ( *(&Str + j) != byte_424040[j] )
    19. goto LABEL_2;
    20. }
    21. puts("Good Job!\n");
    22. }
    23. else
    24. {
    25. LABEL_2:
    26. puts("Error!\n");
    27. }
    28. return 0;
    29. }

    这里sub_41644A()极其复杂,网上有人猜出是加序号再异或序号,但不完全对。不过可以肯定每次仅对一个字符处理时不涉及其它字符,这个就可以爆破了,先用程序patch一下比对的位数,逐位复制程序

    1. data = list(open('attachment.exe', 'rb').read())
    2. for i in range(22):
    3. data[0x15a06] = i
    4. filename = f"aaa{i}.exe"
    5. open(filename, 'wb').write(bytes(data))

    然后再逐位爆破

    1. flag = ''
    2. for i in range(1):
    3. filename = f".\\aaa{i}.exe"
    4. p = subprocess.Popen('.\\aaa0.exe', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
    5. print('pid', p.pid)
    6. print('s', p.stdout.readline())
    7. for j in range(0x21, 0x7f):
    8. tmp = ((flag+chr(j)).ljust(22,'A')+'\n').encode()
    9. print('tmp:', tmp)
    10. p.stdin.write(tmp)
    11. p.stdin.flush()
    12. out = p.stdout.readline()
    13. print("A:",out)
    14. if b'Error' not in out:
    15. flag += chr(j)
    16. print(flag)
    17. break
    18. #npuctf{WDNMD_LJ_OBFU!}

    127_[SUCTF2019]Akira Homework

    皮皮蟹 

    128_[GKCTF 2021]app-debug

    这是个apk文件,先用jd打开找到Resources/AndroidManifest.xml 看里边的内容<activity android:name="com.example.myapplication.MainActivity"> 这是起点

    从这里找到flag打包方式

    1. public class MainActivity extends AppCompatActivity {
    2. ......
    3. protected void onCreate(Bundle savedInstanceState) {
    4. ......
    5. this.mBtnLogin.setOnClickListener(new OnClickListener() {
    6. public void onClick(View v) {
    7. MainActivity mainActivity = MainActivity.this;
    8. if (mainActivity.check(mainActivity.mEtflag.getText().toString())) { //调用检查
    9. Toast.makeText(MainActivity.this, "You Are Right!flag is flag{md5(input)}", 0).show(); //flag组装方式
    10. } else {
    11. Toast.makeText(MainActivity.this, "Sorry your flag is wrong!", 0).show();
    12. }
    13. }
    14. });
    15. }
    16. }

    我核对函数,这个函数在lib里lib\arm64-v8a\libnative-lib.so

    用IDA打开找到对应函数

    1. bool __fastcall Java_com_example_myapplication_MainActivity_check(__int64 a1, __int64 a2, __int64 a3)
    2. {
    3. ...
    4. if ( sub_40040((__int64)v6) == 7 )
    5. {
    6. for ( i = 0; i <= 6; ++i )
    7. byte_C80E0[i] = *(_BYTE *)sub_40064((__int64)v6, i);
    8. v5 = sub_3ED8C((unsigned int *)byte_C80E0); //加密函数
    9. }
    10. }
    11. bool __fastcall sub_3ED8C(unsigned int *a1)
    12. {
    13. ...
    14. v5 = *a1;
    15. v4 = a1[1];
    16. v3 = 0;
    17. for ( i = 0; i < 0x20; ++i )
    18. {
    19. v3 += dword_C8010;
    20. v5 += (16 * v4 + dword_C8000) ^ (v4 + v3) ^ ((v4 >> 5) + dword_C8004);
    21. v4 += (16 * v5 + dword_C8008) ^ (v5 + v3) ^ ((v5 >> 5) + dword_C800C);
    22. }
    23. *a1 = v5;
    24. a1[1] = v4;
    25. return *a1 == 0xF5A98FF3 && a1[1] == 0xA21873A3;

    处理完运行发现不对。原来这里也用了反调,在.init_array里有函数

    .init_array:00000000000C0F98 3C EF 03 00 00 00 00 00       off_C0F98 DCQ sub_3EF3C

    函数对几个key 作了变更

    1. __int64 sub_3EF3C()
    2. {......
    3. if ( !strcmp(s1, "0") )
    4. sub_3EF18();
    5. }
    6. void sub_3EF18()
    7. {
    8. dword_C8004 = 7;
    9. dword_C8008 = 8;
    10. dword_C800C = 6;
    11. }

    根据新的key写出程序

    1. c8010 = 0x458BCD42
    2. c8000 = 9
    3. c8004 = 7
    4. c8008 = 8
    5. c800c = 6
    6. v3 = c8010 *0x20
    7. v5 = 0xF5A98FF3
    8. v4 = 0xA21873A3
    9. for i in range(0x1f,-1,-1):
    10. v4 -= (16 * v5 + c8008) ^ ( v5 + v3) ^ ((v5 >> 5) + c800c)
    11. v4 &= 0xffffffff
    12. v5 -= (16 * v4 + c8000) ^ ( v4 + v3) ^ ((v4 >> 5) + c8004)
    13. v5 &= 0xffffffff
    14. v3 -= c8010
    15. v3 &= 0xffffffff
    16. print(v5, v4,v3)
    17. print(bytes.fromhex(hex(v5)[2:])[::-1]+bytes.fromhex(hex(v4)[2:])[::-1])
    18. #GKcTFg0
    19. m = b'GKcTFg0'
    20. from hashlib import md5
    21. print(md5(m).digest().hex())
    22. #flag{77bca47fe645ca1bd1ac93733171c9c4}

    129_[FlareOn2]YUSoMeta

    打开发现是.net的程序,用dnSpy打开发现有混淆,用de4dot处理一下,再打开一个,找到main,

    1. string text = Console.ReadLine().Trim(); //读取输入的密码
    2. string b = Class3.smethod_0(class1_, byte_2) + '_' + Class3.smethod_3();
    3. if (text == b)
    4. {
    5. Console.WriteLine(Encoding.ASCII.GetString(bytes4)); //Thank you for providing the correct password.
    6. Console.Write(Encoding.ASCII.GetString(bytes5)); //Use the following email address to proceed to the next challenge:
    7. Console.WriteLine(Class3.smethod_1(text, byte_));
    8. return;
    9. }

    再回到原来没处理过的程序,在比较这个位置下断点,然后执行

     执行到断点后可以看到对比的数据

    metaprogrammingisherd_DD9BE1704C690FB422F1509A46ABC988

    运行程序输入这个密码得到flag

    1. C:\buuctf.reverse\129_[FlareOn2]YUSoMeta>YUSoMeta
    2. Warning! This program is 100% tamper-proof!
    3. Please enter the correct password: metaprogrammingisherd_DD9BE1704C690FB422F1509A46ABC988
    4. Thank you for providing the correct password.
    5. Use the following email address to proceed to the next challenge: Justr3adth3sourc3@flare-on.com
    6. #flag{Justr3adth3sourc3@flare-on.com}

    130_[GXYCTF2019]minecraft

    ida打开后发现它处理的东西在函数String_t0_intDll里,打开dll文件(函数在dll文件中),打开主要加密逻辑

    1. _BOOL8 __fastcall String_to_long(__int64 a1)
    2. {
    3. void *v2; // rax
    4. char v3; // [rsp+30h] [rbp-138h]
    5. int j; // [rsp+34h] [rbp-134h]
    6. int v5; // [rsp+38h] [rbp-130h]
    7. int i; // [rsp+3Ch] [rbp-12Ch]
    8. _QWORD *v7; // [rsp+48h] [rbp-120h]
    9. __int64 v8; // [rsp+50h] [rbp-118h]
    10. _QWORD *v9; // [rsp+58h] [rbp-110h]
    11. int v10[8]; // [rsp+60h] [rbp-108h]
    12. char *v11; // [rsp+80h] [rbp-E8h]
    13. const struct std::_Container_base0 *v12; // [rsp+88h] [rbp-E0h]
    14. __int64 v13; // [rsp+90h] [rbp-D8h]
    15. __int64 v14; // [rsp+98h] [rbp-D0h]
    16. char *v15; // [rsp+A0h] [rbp-C8h]
    17. const struct std::_Container_base0 *v16; // [rsp+A8h] [rbp-C0h]
    18. char v17[32]; // [rsp+B0h] [rbp-B8h] BYREF
    19. char v18[32]; // [rsp+D0h] [rbp-98h] BYREF
    20. char v19[32]; // [rsp+F0h] [rbp-78h] BYREF
    21. char v20[32]; // [rsp+110h] [rbp-58h] BYREF
    22. char v21[32]; // [rsp+130h] [rbp-38h] BYREF
    23. v7 = operator new(0x128ui64);
    24. if ( v7 )
    25. {
    26. *v7 = 9i64;
    27. `eh vector constructor iterator'(v7 + 1, 0x20ui64, 9ui64, sub_180003C90, (void (__stdcall *)(void *))sub_180003AF0);
    28. v9 = v7 + 1;
    29. }
    30. else
    31. {
    32. v9 = 0i64;
    33. }
    34. sub_180003C90(v20);
    35. v11 = v18;
    36. v12 = sub_180003CE0((const struct std::_Container_base0 *)v18, a1);
    37. v8 = sub_1800033E0(v12); // base64
    38. if ( (unsigned __int64)unknown_libname_105(a1) >= 0xA )
    39. {
    40. sub_180003A60((__int64)v20, v8);
    41. v5 = 0;
    42. for ( i = 0; ; ++i )
    43. {
    44. v13 = v5;
    45. if ( v5 >= (unsigned __int64)unknown_libname_105(v20) )
    46. break;
    47. v14 = sub_180003900(v20, v17, v5, 4i64);
    48. sub_180003B20(&v9[4 * i], v14);
    49. ((void (__stdcall *)(void *))sub_180003AF0)(v17);
    50. sub_1800039E0(&v9[4 * i], &unk_180034570);
    51. v5 += 4; // 每4个一组分组
    52. }
    53. sub_180003C90(v21);
    54. for ( j = 0; j < 8; ++j )
    55. {
    56. sub_180003A90(v21, &v9[4 * j]);
    57. v15 = v19;
    58. v16 = sub_180003CE0((const struct std::_Container_base0 *)v19, (__int64)v21);
    59. v10[j] = sub_180003390(v16); // hash
    60. }
    61. v3 = 0;
    62. v2 = (void *)sub_180004B90(&qword_18003A200, "-------Checking-----");
    63. _CallMemberFunction0(v2, sub_180004F60);
    64. if ( v10[0] == 0x6C43B2A7
    65. && v10[1] == 0x7954FD91
    66. && v10[2] == 0xA3E9532
    67. && v10[3] == 0xB87B5156
    68. && v10[4] == 0xDA847742
    69. && v10[5] == 0x2395E7F3
    70. && v10[6] == 0xA679D954
    71. && v10[7] == 0xE1FAAFF7 )
    72. {
    73. v3 = 1;
    74. }
    75. sub_180003310(v9, v8);
    76. ((void (__stdcall *)(void *))sub_180003AF0)(v21);
    77. ((void (__stdcall *)(void *))sub_180003AF0)(v20);
    78. return v3 != 0;
    79. }
    80. else
    81. {
    82. ((void (__stdcall *)(void *))sub_180003AF0)(v20);
    83. return 0i64;
    84. }
    85. }

    先是base64再每4个一组作个自定义的hash再比较,hash比较深

    1. __int64 __fastcall sub_180003390(void *a1)
    2. {
    3. unsigned int v2; // [rsp+20h] [rbp-18h]
    4. char v3[4]; // [rsp+24h] [rbp-14h] BYREF
    5. v2 = unknown_libname_104(v3, a1); // hash
    6. sub_180003AF0(a1);
    7. return v2;
    8. }
    9. // Microsoft VisualC 64bit universal runtime
    10. __int64 __fastcall unknown_libname_104(__int64 a1, __int64 a2)
    11. {
    12. return sub_180004B40(a2); // call hash
    13. }
    14. __int64 __fastcall sub_180004B40(__int64 a1)
    15. {
    16. __int64 *v1; // rax
    17. __int64 *v3; // [rsp+20h] [rbp-28h]
    18. char v4[8]; // [rsp+28h] [rbp-20h] BYREF
    19. char v5[24]; // [rsp+30h] [rbp-18h] BYREF
    20. v3 = (__int64 *)sub_1800059D0(a1, v4);
    21. v1 = (__int64 *)sub_180005A30(a1, v5);
    22. return sub_180005FB0(*v1, *v3); // call hash
    23. }
    24. __int64 __fastcall sub_180005FB0(__int64 a1, __int64 a2)
    25. {
    26. unsigned __int8 *v2; // rax
    27. __int64 v4; // [rsp+20h] [rbp-18h] BYREF
    28. __int64 v5; // [rsp+40h] [rbp+8h] BYREF
    29. __int64 v6; // [rsp+48h] [rbp+10h] BYREF
    30. v6 = a2;
    31. v5 = a1;
    32. v4 = 0i64;
    33. while ( (unsigned __int8)sub_180006100(&v5, &v6) )
    34. {
    35. v2 = (unsigned __int8 *)unknown_libname_107(&v5);
    36. sub_180006200(&v4, v2); // call hash
    37. std::_String_const_iterator<std::_String_val<std::_Simple_types<char>>>::operator++(&v5);
    38. }
    39. return v4;
    40. }
    41. __int64 __fastcall sub_180006200(__int64 *a1, unsigned __int8 *a2)
    42. {
    43. __int64 v2; // rax
    44. char v4[8]; // [rsp+20h] [rbp-18h] BYREF
    45. v2 = sub_180002E00(v4, *a2);
    46. return hash_180002D30(a1, v2);
    47. }
    48. __int64 __fastcall sub_180002D30(__int64 *a1, __int64 a2)
    49. {
    50. __int64 result; // rax
    51. *a1 ^= 0xC6A4A7935BD1E995ui64 * (((0xC6A4A7935BD1E995ui64 * a2) >> 47) ^ (0xC6A4A7935BD1E995ui64 * a2));
    52. *a1 *= 0xC6A4A7935BD1E995ui64;
    53. result = *a1 + 0xE6546B64i64;
    54. *a1 = result;
    55. return result;
    56. }

    然后根据这个每3个字符一组进行爆破

    1. from itertools import product
    2. import string
    3. from base64 import b64encode
    4. c = [0x6C43B2A7,0x7954FD91,0xA3E9532,0xB87B5156,0xDA847742,0x2395E7F3,0xA679D954,0xE1FAAFF7]
    5. '''
    6. String_t0_intDll.dll sub_180002D30
    7. *a1 ^= 0xC6A4A7935BD1E995ui64 * (((0xC6A4A7935BD1E995ui64 * a2) >> 47) ^ (0xC6A4A7935BD1E995ui64 * a2));
    8. *a1 *= 0xC6A4A7935BD1E995ui64;
    9. result = *a1 + 0xE6546B64i64;
    10. *a1 = result;
    11. '''
    12. def hash(v):
    13. n = b64encode(''.join(v).encode())
    14. delta = 0xC6A4A7935BD1E995
    15. ret = 0
    16. for i in range(4):
    17. ret ^= delta * ((((delta * n[i])&0xffffffffffffffff)>>47) ^ (delta * n[i]))
    18. ret *= delta
    19. ret += 0xE6546B64
    20. return ret&0xffffffff
    21. chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{}_-!?'
    22. flag = ['']*8
    23. def bp():
    24. for v in product(chars, repeat=3): #
    25. m = hash(v)
    26. if m in c:
    27. flag[c.index(m)]= ''.join(v)
    28. print(c.index(m), v)
    29. bp()
    30. print(''.join(flag))
    31. #GXY{I_have_no_gir1_frieN
    32. #flag{I_have_no_gir1_frieNd}

  • 相关阅读:
    推荐计算机领域的几本入门书籍
    2407. 最长递增子序列 II(dp)
    Golang 中的 errors 包详解:返回自定义 error 类型
    基于Python的图书借阅管理系统,附源码
    运行.sln 32/64位程序,启动不了,无法显示界面
    Python的计算性能优化
    计算机等级考试信息安全三级填空题-二
    Java多线程
    nginx的详解与应用
    【minitab】--logistic回归
  • 原文地址:https://blog.csdn.net/weixin_52640415/article/details/125449026