666

先看一下,这是多少位的ELF文件
48429-czsoxiwaml6.png

然后我们查看一波他的字符串,发现了个fake的flag(一眼丁真),咱们就从这fake入手去分析
68641-31bfc8qd8do.png

99800-gfhdjrzld76.png

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s; // [rsp+0h] [rbp-1E0h]
  char v5; // [rsp+F0h] [rbp-F0h]

  memset(&s, 0, 0x1EuLL);
  printf("Please Input Key: ", 0LL);
  __isoc99_scanf("%s", &v5); //scanf这里输入字符串
  encode(&v5, &s);  //encode函数可以看出应该是要把输入进来的v5进行加密然后赋值到s
  if ( strlen(&v5) == key )//判断v5字符串的长度是否与key的长度一致
  {
    if ( !strcmp(&s, enflag) ) //比较s的长度是否与enflag相同
      puts("You are Right");
    else
      puts("flag{This_1s_f4cker_flag}");
  }
  return 0;
}

接下来进入encode函数看看,他是怎么加密v5的
82017-n762cou5bc.png

这是一个简单的异或操作。我们接下来看一眼enflag的值
03743-oyblcs86vlc.png

最后根据加密后的值和加密算法,写出脚本
17836-aanes8uzwih.png

Shuffle

40262-d1c51wuaq4.png

这里发现是32位的ELF文件。我们进入main函数分析一波
26156-jex14wj6un.png

  v50 = __readgsdword(0x14u);
  s = 83;
  v11 = 69;
  v12 = 67;
  v13 = 67;
  v14 = 79;
  v15 = 78;
  v16 = 123;
  v17 = 87;
  v18 = 101;
  v19 = 108;
  v20 = 99;
  v21 = 111;
  v22 = 109;
  v23 = 101;
  v24 = 32;
  v25 = 116;
  v26 = 111;
  v27 = 32;
  v28 = 116;
  v29 = 104;
  v30 = 101;
  v31 = 32;
  v32 = 83;
  v33 = 69;
  v34 = 67;
  v35 = 67;
  v36 = 79;
  v37 = 78;
  v38 = 32;
  v39 = 50;
  v40 = 48;
  v41 = 49;
  v42 = 52;
  v43 = 32;
  v44 = 67;
  v45 = 84;
  v46 = 70;
  v47 = 33;
  v48 = 125;
  v49 = 0;
  v3 = time(0);
  v4 = getpid();
  srand(v3 + v4);
  for ( i = 0; i <= 99; ++i )
  {
    v5 = rand() % 0x28u;
    v6 = rand() % 0x28u;
    v7 = *(&s + v5);
    *(&s + v5) = *(&s + v6);
    *(&s + v6) = v7;
  }
  puts(&s);
  return 0;
}

这里发现从s-v49有些奇特,转字符后发现直接获得FLAG
76366-t1q7wu2987.png

FLAG值为SECCON{Welcome to the SECCON 2014 CTF!}

srm-50

01416-xcwkvugw1iq.png

看出是32位exe。用ida32打开
我们先在exe里随便输入个值看一下返回数据
06041-viqxqpdu30j.png

接着来字符串区域搜索一下
40000-l2gjki953ta.png

然后点击该字符串,并对其进行伪代码查看
02781-s7rm0cz9vg.png

BOOL __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
  HMODULE v5; // eax
  HICON v6; // eax
  HMODULE v7; // eax
  HCURSOR v8; // ST20_4
  HWND v9; // eax
  CHAR String; // [esp+8h] [ebp-340h]
  CHAR v11[4]; // [esp+108h] [ebp-240h]
  char v12; // [esp+10Ch] [ebp-23Ch]
  char v13; // [esp+10Dh] [ebp-23Bh]
  char v14; // [esp+10Eh] [ebp-23Ah]
  char v15; // [esp+10Fh] [ebp-239h]
  char v16; // [esp+110h] [ebp-238h]
  char v17; // [esp+111h] [ebp-237h]
  char v18; // [esp+112h] [ebp-236h]
  char v19; // [esp+113h] [ebp-235h]
  char v20; // [esp+114h] [ebp-234h]
  char v21; // [esp+115h] [ebp-233h]
  char v22; // [esp+116h] [ebp-232h]
  char v23; // [esp+117h] [ebp-231h]
  CHAR Text; // [esp+208h] [ebp-140h]
  char Src[16]; // [esp+308h] [ebp-40h]
  __int128 v26; // [esp+318h] [ebp-30h]
  int v27; // [esp+328h] [ebp-20h]
  __int128 v28; // [esp+32Ch] [ebp-1Ch]
  int v29; // [esp+33Ch] [ebp-Ch]
  __int16 v30; // [esp+340h] [ebp-8h]

  if ( a2 == 16 )
  {
    EndDialog(hDlg, 0);
    return 0;
  }
  if ( a2 == 272 )
  {
    v5 = GetModuleHandleW(0);
    v6 = LoadIconW(v5, (LPCWSTR)0x67);
    SetClassLongA(hDlg, -14, (LONG)v6);
    v7 = GetModuleHandleW(0);
    v8 = LoadCursorW(v7, (LPCWSTR)0x66);
    v9 = GetDlgItem(hDlg, 1);
    SetClassLongA(v9, -12, (LONG)v8);
    return 1;
  }
  if ( a2 != 273 || (unsigned __int16)a3 != 1 )
    return 0;
  memset(&String, (unsigned __int16)a3 - 1, 0x100u);
  memset(v11, 0, 0x100u);
  memset(&Text, 0, 0x100u);
  GetDlgItemTextA(hDlg, 1001, &String, 256);
  GetDlgItemTextA(hDlg, 1002, v11, 256);
  if ( strstr(&String, "@") && strstr(&String, ".") && strstr(&String, ".")[1] && strstr(&String, "@")[1] != 46 )
  {
    v28 = xmmword_410AA0;
    v29 = 1701999980;
    *(_OWORD *)Src = xmmword_410A90;
    v30 = 46;
    v26 = xmmword_410A80;
    v27 = 3830633;
    if ( strlen(v11) != 16
      || v11[0] != 67
      || v23 != 88
      || v11[1] != 90
      || v11[1] + v22 != 155
      || v11[2] != 57
      || v11[2] + v21 != 155
      || v11[3] != 100
      || v20 != 55
      || v12 != 109
      || v19 != 71
      || v13 != 113
      || v13 + v18 != 170
      || v14 != 52
      || v17 != 103
      || v15 != 99
      || v16 != 56 )
    {
      strcpy_s(&Text, 0x100u, (const char *)&v28);
    }
    else
    {
      strcpy_s(&Text, 0x100u, Src);
      strcat_s(&Text, 0x100u, v11);
    }
  }
  else
  {
    strcpy_s(&Text, 0x100u, "Your E-mail address in not valid.");
  }
  MessageBoxA(hDlg, &Text, "Registeration", 0x40u);
  return 1;
}

下图这串代码就是判断用户名里是否存在“@”和“.”即判断邮箱的正确格式
04545-ds7enro9jyf.png

这里就是说明密码有十六位长度,且下面那些ascii码转为chr就是密码的值(记得按顺序输入)
79645-mtek9d6e6p.png

密码为:CZ9dmq4c8g9G7bAX

52461-wi7w7c0uyw.png

Mysterious

依旧还是win32的程序。
首先我随便输入下数据,发现毫无反应,放入ida静态分析
75431-a4tdp0kb1nw.png

根据字符串,进入到伪代码窗口
55624-8dzntxpaopl.png

15904-9nm4sscp7s.png

int __stdcall sub_401090(HWND hWnd, int a2, int a3, int a4)
{
  char v5; // [esp+50h] [ebp-310h]
  CHAR Text[4]; // [esp+154h] [ebp-20Ch]
  char v7; // [esp+159h] [ebp-207h]
  __int16 v8; // [esp+255h] [ebp-10Bh]
  char v9; // [esp+257h] [ebp-109h]
  int v10; // [esp+258h] [ebp-108h]
  CHAR String; // [esp+25Ch] [ebp-104h]
  char v12; // [esp+25Fh] [ebp-101h]
  char v13; // [esp+260h] [ebp-100h]
  char v14; // [esp+261h] [ebp-FFh]

  memset(&String, 0, 0x104u);
  v10 = 0;
  if ( a2 == 16 )
  {
    DestroyWindow(hWnd);
    PostQuitMessage(0);
  }
  else if ( a2 == 273 )
  {
    if ( a3 == 1000 )
    {
      GetDlgItemTextA(hWnd, 1002, &String, 260);//输入字符串
      strlen(&String);
      if ( strlen(&String) > 6 )//判断字符串长度是否>6
        ExitProcess(0);
      v10 = atoi(&String) + 1;  //将字符串转换为整型后+1
      if ( v10 == 123 && v12 == 'x' && v14 == 'z' && v13 == 'y' )//根据这几个是连续地址可以判断出,他们代表着输入的值。所以,当输入的值为122xyz时候即可继续往下走
      {
        strcpy(Text, "flag");//将flag赋予Text
        memset(&v7, 0, 0xFCu);
        v8 = 0;
        v9 = 0;
        _itoa(v10, &v5, 10);//将字符串化为整型
        strcat(Text, "{");//将俩个参数拼接,下面意思一样
        strcat(Text, &v5);
        strcat(Text, "_");
        strcat(Text, "Buff3r_0v3rf|0w");
        strcat(Text, "}");
        MessageBoxA(0, Text, "well done", 0);//MessageBoxA就是信息窗口,这里直接输出
      }
      SetTimer(hWnd, 1u, 0x3E8u, TimerFunc);
    }
    if ( a3 == 1001 )
      KillTimer(hWnd, 1u);
  }
  return 0;
}

所以根据对代码的分析,我们可以通过输入122xyz或者直接从源码中就可以得出flag
04188-naovqrhp8wa.png

re4-unvm-me

这题是个pyc反编译
33271-9uvp8uy1ger.png

我们利用在线反编译网站来反编译下pyc https://tool.lu/pyc
88382-vqgvoo615b.png

import md5
md5s = [
    0x831DAA3C843BA8B087C895F0ED305CE7L,
    0x6722F7A07246C6AF20662B855846C2C8L,
    0x5F04850FEC81A27AB5FC98BEFA4EB40CL,
    0xECF8DCAC7503E63A6A3667C5FB94F610L,
    0xC0FD15AE2C3931BC1E140523AE934722L,
    0x569F606FD6DA5D612F10CFB95C0BDE6DL,
    0x68CB5A1CF54C078BF0E7E89584C1A4EL,
    0xC11E2CD82D1F9FBD7E4D6EE9581FF3BDL,
    0x1DF4C637D625313720F45706A48FF20FL,
    0x3122EF3A001AAECDB8DD9D843C029E06L,
    0xADB778A0F729293E7E0B19B96A4C5A61L,
    0x938C747C6A051B3E163EB802A325148EL,
    0x38543C5E820DD9403B57BEFF6020596DL]
print 'Can you turn me back to python ? ...'
flag = raw_input('well as you wish.. what is the flag: ')
if len(flag) > 69:
    print 'nice try'
    exit()
if len(flag) % 5 != 0:
    print 'nice try'
    exit()
for i in range(0, len(flag), 5):
    s = flag[i:i + 5]
    if int('0x' + md5.new(s).hexdigest(), 16) != md5s[i / 5]:
        print 'nice try'
        exit()
        continue
print 'Congratz now you have the flag'

这里是一个用python2.7写的python。只需要把上方那些16进制的md5一个个解密下就好了
如下图
55610-dvejyfbduzn.png

最后得出flag

ALEXCTF{dv5d4s2vj8nk43s8d8l6m1n5l67ds9v41n52nv37j481h3d28n4b6v3k}

流浪者

41682-h331nkjh3yq.png

可以看到是c++写的32位无壳程序
我们用ida静态调试下
67063-qnfm44nnqs.png

先从字符串窗口找个字符串反编译一下
95072-7z0hikpsmvu.png

由下图可知sub_401770()代表了正确的函数
07779-75osp99r03y.png

接下来返回上个函数sub_4017F0()看看
18506-naw6om21o7.png

int __thiscall sub_401890(CWnd *this)
{
  struct CString *v1; // ST08_4
  CWnd *v2; // eax
  int v3; // eax
  int v5[26]; // [esp+4Ch] [ebp-74h]
  int i; // [esp+B4h] [ebp-Ch]
  char *Str; // [esp+B8h] [ebp-8h]
  CWnd *v8; // [esp+BCh] [ebp-4h]

  v8 = this;
  v1 = (CWnd *)((char *)this + 100);
  v2 = CWnd::GetDlgItem(this, 1002);
  CWnd::GetWindowTextA(v2, v1);
  v3 = sub_401A30((char *)v8 + 100);
  Str = CString::GetBuffer((CWnd *)((char *)v8 + 100), v3);
  if ( !strlen(Str) )
    return CWnd::MessageBoxA(v8, "请输入pass!", 0, 0);
  for ( i = 0; Str[i]; ++i )
  {
    if ( Str[i] > 57 || Str[i] < 48 )
    {
      if ( Str[i] > 122 || Str[i] < 97 )
      {
        if ( Str[i] > 90 || Str[i] < 65 )
          sub_4017B0();//这里三个if来判断字符串的范围
        else
          v5[i] = Str[i] - 29;
      }
      else
      {
        v5[i] = Str[i] - 87;
      }
    }
    else
    {
      v5[i] = Str[i] - 48;
    }
  }
  return sub_4017F0((int)v5);//将修改后的v5传入
}

sub_4017F0的代码

BOOL __cdecl sub_4017F0(int a1)
{
  BOOL result; // eax
  char Str1[28]; // [esp+D8h] [ebp-24h]
  int v3; // [esp+F4h] [ebp-8h]
  int v4; // [esp+F8h] [ebp-4h]

  v4 = 0;
  v3 = 0;
  while ( *(_DWORD *)(a1 + 4 * v4) < 62 && *(_DWORD *)(a1 + 4 * v4) >= 0 )//0<=a1[v4]<=62
  {
    Str1[v4] = aAbcdefghiabcde[*(_DWORD *)(a1 + 4 * v4)];//密文 
                                  abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQRSTUVWXYZ
    ++v4;
  }
  Str1[v4] = 0;
  if ( !strcmp(Str1, "KanXueCTF2019JustForhappy") )
    result = sub_401770();
  else
    result = sub_4017B0();
  return result;
}

根据上面来写个脚本
18246-fedd03otkr.png

这里得到了a1即v5的值,接下来我们写主函数的逆向脚本
93778-prwl5y930x.png

得出flag

flag{j0rXI4bTeustBiIGHeCF70DDM}

Reversing-x64Elf-100

61816-dn152j7146l.png

__int64 __fastcall main(int a1, char **a2, char **a3)

{
char s[264]; // [rsp+0h] [rbp-110h] BYREF
unsigned __int64 v5; // [rsp+108h] [rbp-8h]

v5 = __readfsqword(0x28u);
printf("Enter the password: ");
if ( !fgets(s, 255, stdin) )

return 0LL;

if ( (unsigned int)sub_4006FD(s) )
{

puts("Incorrect password!");
return 1LL;

}
else
{

puts("Nice!");
return 0LL;

}
}
sub_4006FD函数很明显是用来判断输入是否正常的,所以现在点进去进去看看

signed __int64 __fastcall sub_4006FD(__int64 a1)

{
signed int i; // [rsp+14h] [rbp-24h]
const char *v3; // [rsp+18h] [rbp-20h]
const char *v4; // [rsp+20h] [rbp-18h]
const char *v5; // [rsp+28h] [rbp-10h]

v3 = "Dufhbmf";
v4 = "pG`imos";
v5 = "ewUglpt";
for ( i = 0; i <= 11; ++i )
{

if ( (&v3)[i % 3][2 * (i / 3)] - *(char *)(i + a1) != 1 )
  return 1LL;

}
return 0LL;
}
因为要使其返回为0,才代表输入的字符串正确,所以我们最后需要将(&v3)i % 3 - (char )(i + a1)=1。后得到如下脚本
48483-9zugb0ygukw.png

发表评论