CTF 简单的reverse

简介: CTF 简单的reverse

、Shuffle

题目来源:攻防世界 (xctf.org.cn)

下载附件,没有任何后缀名,看一下16进制

a03812d78c46b829478d87049df3388d.png


elf文件,linux的可执行文件,用od打不开,再用查壳工具试试看

2a3e831df561fa733597df957ffd13f7.png


没有显示出任务有效信息(这工具可能版本老了或者不行了,但是我懒得更新)

用ida打开

ebaa037d332d549e9c478c4466500bb4.png


可以直接看到定义了一串很像flag的字符串

我们再拖到虚拟机里运行看看

59fd801ceb669eb8e628807b831fa0b6.png


仔细观察可以发现,程序输出的就是ida下看到的那一串字符的随机排列

再结合题目提示:找到字符串在随机化之前

b3a1e92bacb5a8b8324ec2ef120b73c4.png


基本确定flag就是那一串字符

SECCON{Welcome to the SECCON 2014 CTF!}

提交正确

二、srm-50

题目来源:攻防世界 (xctf.org.cn)

下载附件,是个exe,我们还是放虚拟机里运行一下(最近被某群的群文件放马整怕了)

24206f1cf1bd44884dd93c0e4f74cd55.png


fa6e0df8048412be4d5a0e5b6d8ee356.png


是个登入框

用ida打开,shift+f12找之前错误提示的字符

fb1b03eafbdd8aefed7290deef053e5a.png

跟踪过去

d2a44c69a268a455a7b35eef21efd038.png


这边反汇编没反应,开始看汇编,虽然会一些汇编,但是不扎实,汇编代码还是看得头疼,果断放弃,去找main函数

找到main函数,反汇编得到代码

f3bccfcdf34a722d1b3639f9cd5addd5.png

关键看这边提示成功的字符,

5025875dc0b1d93fc9f7508a63401afa.png


那我们就把下面的V11给他转一下应该就是flag了

c38837db077c0373780bef2d2d8247aa.png


86831324c42875717c547c892e1fe0dc.png


那么flag就是:CZ9dmq4c8g9G7bAX

提交正确

三、dmd-50

题目来源:攻防世界 (xctf.org.cn)

下载附件,查看信息,是个elf

5592043b53425ad12266f7081cb23a3e.png


运行一下,是个验证

04ccccf43f6962f4c10e05cf0ad0c470.png


老规矩,上ida,找enter the valid key,再反汇编一下

5577303bf10eb4be76268daa9ce95ec6.png


int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rax
  __int64 v4; // rax
  __int64 v5; // rax
  __int64 v6; // rax
  __int64 v7; // rax
  __int64 v8; // rax
  __int64 v9; // rax
  __int64 v10; // rax
  __int64 v11; // rax
  __int64 v12; // rax
  __int64 v13; // rax
  __int64 v14; // rax
  __int64 v15; // rax
  __int64 v16; // rax
  __int64 v17; // rax
  __int64 v18; // rax
  __int64 v19; // rax
  __int64 v20; // rax
  __int64 v21; // rax
  int result; // eax
  __int64 v23; // rax
  __int64 v24; // rax
  __int64 v25; // rax
  __int64 v26; // rax
  __int64 v27; // rax
  __int64 v28; // rax
  __int64 v29; // rax
  __int64 v30; // rax
  __int64 v31; // rax
  __int64 v32; // rax
  __int64 v33; // rax
  __int64 v34; // rax
  __int64 v35; // rax
  __int64 v36; // rax
  __int64 v37; // rax
  char v38; // [rsp+Fh] [rbp-71h] BYREF
  char v39[16]; // [rsp+10h] [rbp-70h] BYREF
  char v40[8]; // [rsp+20h] [rbp-60h] BYREF
  __int64 v41; // [rsp+28h] [rbp-58h]
  char v42[56]; // [rsp+30h] [rbp-50h] BYREF
  unsigned __int64 v43; // [rsp+68h] [rbp-18h]
  v43 = __readfsqword(0x28u);
  std::operator<<<std::char_traits<char>>(&std::cout, "Enter the valid key!\n", envp);
  std::operator>><char,std::char_traits<char>>(&edata, v42);
  std::allocator<char>::allocator(&v38);
  std::string::string(v39, v42, &v38);
  md5(v40, v39);
  v41 = std::string::c_str((std::string *)v40);
  std::string::~string((std::string *)v40);
  std::string::~string((std::string *)v39);
  std::allocator<char>::~allocator(&v38);
  if ( *(_WORD *)v41 == 14391
    && *(_BYTE *)(v41 + 2) == 48
    && *(_BYTE *)(v41 + 3) == 52
    && *(_BYTE *)(v41 + 4) == 51
    && *(_BYTE *)(v41 + 5) == 56
    && *(_BYTE *)(v41 + 6) == 100
    && *(_BYTE *)(v41 + 7) == 53
    && *(_BYTE *)(v41 + 8) == 98
    && *(_BYTE *)(v41 + 9) == 54
    && *(_BYTE *)(v41 + 10) == 101
    && *(_BYTE *)(v41 + 11) == 50
    && *(_BYTE *)(v41 + 12) == 57
    && *(_BYTE *)(v41 + 13) == 100
    && *(_BYTE *)(v41 + 14) == 98
    && *(_BYTE *)(v41 + 15) == 48
    && *(_BYTE *)(v41 + 16) == 56
    && *(_BYTE *)(v41 + 17) == 57
    && *(_BYTE *)(v41 + 18) == 56
    && *(_BYTE *)(v41 + 19) == 98
    && *(_BYTE *)(v41 + 20) == 99
    && *(_BYTE *)(v41 + 21) == 52
    && *(_BYTE *)(v41 + 22) == 102
    && *(_BYTE *)(v41 + 23) == 48
    && *(_BYTE *)(v41 + 24) == 50
    && *(_BYTE *)(v41 + 25) == 50
    && *(_BYTE *)(v41 + 26) == 53
    && *(_BYTE *)(v41 + 27) == 57
    && *(_BYTE *)(v41 + 28) == 51
    && *(_BYTE *)(v41 + 29) == 53
    && *(_BYTE *)(v41 + 30) == 99
    && *(_BYTE *)(v41 + 31) == 48 )
  {
    v3 = std::operator<<<std::char_traits<char>>(&std::cout, 84LL);
    v4 = std::operator<<<std::char_traits<char>>(v3, 104LL);
    v5 = std::operator<<<std::char_traits<char>>(v4, 101LL);
    v6 = std::operator<<<std::char_traits<char>>(v5, 32LL);
    v7 = std::operator<<<std::char_traits<char>>(v6, 107LL);
    v8 = std::operator<<<std::char_traits<char>>(v7, 101LL);
    v9 = std::operator<<<std::char_traits<char>>(v8, 121LL);
    v10 = std::operator<<<std::char_traits<char>>(v9, 32LL);
    v11 = std::operator<<<std::char_traits<char>>(v10, 105LL);
    v12 = std::operator<<<std::char_traits<char>>(v11, 115LL);
    v13 = std::operator<<<std::char_traits<char>>(v12, 32LL);
    v14 = std::operator<<<std::char_traits<char>>(v13, 118LL);
    v15 = std::operator<<<std::char_traits<char>>(v14, 97LL);
    v16 = std::operator<<<std::char_traits<char>>(v15, 108LL);
    v17 = std::operator<<<std::char_traits<char>>(v16, 105LL);
    v18 = std::operator<<<std::char_traits<char>>(v17, 100LL);
    v19 = std::operator<<<std::char_traits<char>>(v18, 32LL);
    v20 = std::operator<<<std::char_traits<char>>(v19, 58LL);
    v21 = std::operator<<<std::char_traits<char>>(v20, 41LL);
    std::ostream::operator<<(v21, &std::endl<char,std::char_traits<char>>);
    result = 0;
  }
  else
  {
    v23 = std::operator<<<std::char_traits<char>>(&std::cout, 73LL);
    v24 = std::operator<<<std::char_traits<char>>(v23, 110LL);
    v25 = std::operator<<<std::char_traits<char>>(v24, 118LL);
    v26 = std::operator<<<std::char_traits<char>>(v25, 97LL);
    v27 = std::operator<<<std::char_traits<char>>(v26, 108LL);
    v28 = std::operator<<<std::char_traits<char>>(v27, 105LL);
    v29 = std::operator<<<std::char_traits<char>>(v28, 100LL);
    v30 = std::operator<<<std::char_traits<char>>(v29, 32LL);
    v31 = std::operator<<<std::char_traits<char>>(v30, 75LL);
    v32 = std::operator<<<std::char_traits<char>>(v31, 101LL);
    v33 = std::operator<<<std::char_traits<char>>(v32, 121LL);
    v34 = std::operator<<<std::char_traits<char>>(v33, 33LL);
    v35 = std::operator<<<std::char_traits<char>>(v34, 32LL);
    v36 = std::operator<<<std::char_traits<char>>(v35, 58LL);
    v37 = std::operator<<<std::char_traits<char>>(v36, 40LL);
    std::ostream::operator<<(v37, &std::endl<char,std::char_traits<char>>);
    result = 0;
  }
  return result;
}

分析代码,看这,应该是个md5

85ed79a501962a1d5f7109a33cb6f20b.png


85行开始往后的那一大串,转化成字符之后,可以发现是程序常量,所以主要看55行开始的那一串就行了

483c12322e9c78ae4ba335093703a789.png


把55行if之后的数据全都拿出来,小端存储,所以我们倒着拿,然后就得到了

780438d5b6e29db0898bc4f0225935c0

再解密试一下,就得到grape

6b8a10a343022a608d8b095d08d0f520.png


到这里其实我有点懵了,看了下wp,这边解密工具给出的grape是经过两次md5运算的,而程序这里只经过了一次,所以再反向加密一次就能够得到flag

97242e893ecf8d50c43b9a68f134f289.png


flag:b781cbb29054db12f88f08c6e161c199

攻防世界,这是一个比较适合新手去练习的一个ctf平台,这些的逆向题目也都不怎么难,尤其第一题都不需要有任何汇编和代码基础,会用ida就能做出来,挺推荐刚接触安全或者想打ctf的朋友去练练的。

玩逆向,基础代码知识得牢固,正向功底越好,逆向才能牛逼,尤其是汇编和C,这两个是躲不开的。多学习,多实践,从0到1,一起加油!


相关文章
|
6月前
|
存储 安全 Shell
[网络安全]upload-labs Pass-12 解题详析
[网络安全]upload-labs Pass-12 解题详析
106 0
|
6月前
|
安全 应用服务中间件 网络安全
[网络安全]upload-labs Pass-06 解题详析
[网络安全]upload-labs Pass-06 解题详析
102 0
|
6月前
|
网络安全
[网络安全]upload-labs Pass-03 解题详析
[网络安全]upload-labs Pass-03 解题详析
115 0
|
6月前
|
网络安全
[网络安全]upload-labs Pass-02 解题详析
[网络安全]upload-labs Pass-02 解题详析
66 0
|
6月前
|
网络安全
[网络安全]upload-labs Pass-10 解题详析
[网络安全]upload-labs Pass-10 解题详析
65 0
|
6月前
|
网络安全 Apache PHP
[网络安全]upload-labs Pass-04 解题详析
[网络安全]upload-labs Pass-04 解题详析
163 0
|
6月前
|
Shell 网络安全
[网络安全]upload-labs Pass-13 解题详析
[网络安全]upload-labs Pass-13 解题详析
109 0
|
6月前
|
网络安全
[网络安全]upload-labs Pass-07 解题详析
[网络安全]upload-labs Pass-07 解题详析
131 0
|
6月前
|
网络安全
[网络安全]upload-labs Pass-21 解题详析
[网络安全]upload-labs Pass-21 解题详析
99 0
|
6月前
|
网络安全 PHP
[网络安全]upload-labs Pass-16 解题详析
[网络安全]upload-labs Pass-16 解题详析
65 0