BUUCTF刷题记录 [Reverse]

BUUCTF刷题记录[Reverse]

SimpleRev

64位无壳程序,重点函数为Decry函数。

0x01 小端序存储

*(_QWORD *)src = 0x534C43444ELL;
v9 = 0x776F646168LL;

IDA直接转字符串的结果是

*(_QWORD *)src = 'SLCDN';
v9 = 'wodah';

Intel的CPU是小端序存储,因此程序载入内存后,字符串顺序应该反过来,也就是

*(_QWORD *)src = 'NDCLS';
v9 = 'hadow';

0x02 大写字母转小写字母

v3 = 0;
getchar();
v5 = strlen(key);
for ( i = 0; i < v5; ++i )
{
  if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )
    key[i] = key[v3 % v5] + 32;
  ++v3;
}

大写字母和小写字母的ASCII码相差32,所以该段程序是将key中的大写字母转成小写字母。

0x03 混淆算法

while ( 1 )
{
  v1 = getchar();
  if ( v1 == 10 )
    break;
  if ( v1 == 32 )
  {
    ++v2;
  }
  else
  {
    if ( v1 <= 96 || v1 > 122 )
    {
      if ( v1 > 64 && v1 <= 90 )
        str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
    }
    else
    {
      str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
    }
    if ( !(v3 % v5) )
      putchar(32);
    ++v2;
  }
}
if ( !strcmp(text, str2) )
  puts("Congratulation!\n");
else
  puts("Try again!\n");

如果对ASCII码熟悉的话,很容易可以看出几个判断条件的目的是确保输入的v1是26的英文字母之一,大小写皆可,因此遍历26个英文字母,依次输出符合条件的字符即可。

0x04 EXP

src = "ADSFKNDCLS"
v3 = 0
v5 = len(src)
key = ""
for i in range(v5):
    if (src[i] > "@" and src[i] <= "Z"):
        key += (chr(ord(src[i]) + 32))
    else:
        key + (src[i])
#print("%s" %key)

text = "killshadow"
flag = ""
while (v3 < 10):
    for i in range(65, 91):
        if (ord(text[v3]) == ((i - 39 - ord(key[v3]) + 97) % 26 + 97)):
            flag += chr(i)
            v3 += 1
            break
        else:
            if (i == 90):
                for j in range(97, 122):
                    if (ord(text[v3]) == ((j - 39 - ord(key[v3]) + 97) % 26 + 97)):
                        flag += chr(j)
                        v3 += 1
                        break
print("flag{%s}" %flag) 

flag{KLDQCUDFZO}

0x05 反思

  1. 大小端存储知识点不熟悉,变量赋值和载入内存时的字符串顺序转换不够熟悉。
  2. ASCII码不熟悉,不清楚函数的意图。

luck_guy

EXP

f1 = "GXY{do_not_"
s = [0x7F, 0x66, 0x6F, 0x60, 0x67, 0x75, 0x63, 0x69][::-1]
f2 = ""
for i in range(8):
    if (i % 2 == 1):
        f2 += chr(int(s[i]) - 2)
    else:
        f2 += chr(int(s[i]) - 1)
flag = f1 + f2
print("%s" %flag)
print("flag%s" %flag[3:])

flag{do_not_hate_me}

[BJDCTF2020]JustRE

比较直接,需要用户点击19999次弹出的框后,打印flag。

INT_PTR __stdcall DialogFunc(HWND hWnd, UINT a2, WPARAM a3, LPARAM a4)
{
  CHAR String; // [esp+0h] [ebp-64h]

  if ( a2 != 272 )
  {
    if ( a2 != 273 )
      return 0;
    if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 )
    {
      sprintf(&String, Format, ++dword_4099F0);
      if ( dword_4099F0 == 19999 )
      {
        sprintf(&String, aBjdDD2069a4579, 19999, 0);// 打印flag
        SetWindowTextA(hWnd, &String);
        return 0;
      }
      SetWindowTextA(hWnd, &String);
      return 0;
    }
    EndDialog(hWnd, (unsigned __int16)a3);
  }
  return 1;
}

直接使用ipython将19999和0填入进去即可。

flag{1999902069a45792d233ac}

刮开有奖

0x01 总体分析

32位无壳,main函数比较简单,它的参数DialogFunc比较有问题。

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
  DialogBoxParamA(hInstance, (LPCSTR)0x67, 0, DialogFunc, 0);
  return 0;
}

DialogBoxParamA函数(winuser.h)

从对话框模板资源创建模式对话框。 在显示对话框之前,函数会将应用程序定义的值作为WM_INITDIALOG消息的 lParam 参数传递给对话框过程。 应用程序可以使用此值初始化对话框控件。

https://learn.microsoft.com/zh-CN/windows/win32/api/winuser/nf-winuser-dialogboxparama

DialogFunc函数中重点代码如下:

  if ( (_WORD)a3 == 1001 )
  {
    memset(&String, 0, 0xFFFFu);
    GetDlgItemTextA(hDlg, 1000, &String, 0xFFFF);
    if ( strlen(&String) == 8 )
    {
      v7 = 'Z';
      v8 = 'J';
      v9 = 'S';
      v10 = 'E';
      v11 = 'C';
      v12 = 'a';
      v13 = 'N';
      v14 = 'H';
      v15 = '3';
      v16 = 'n';
      v17 = 'g';
      sub_4010F0((int)&v7, 0, 10);
      memset(&v26, 0, 0xFFFFu);
      v26 = v23;
      v28 = v25;
      v27 = v24;
      v4 = sub_401000((int)&v26, strlen(&v26));
      memset(&v26, 0, 0xFFFFu);
      v27 = v21;
      v26 = v20;
      v28 = v22;
      v5 = sub_401
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值