南邮 逆向 部分题解

转自: https://blog.csdn.net/xiangshangbashaonian/article/details/78878876

Hello,RE!

首先可以看到提示如下

 

南邮 逆向 部分题解_第1张图片

 

我还是查了一下 无壳

提示用IDA

那我们就载入 shift+f12查找字符串

南邮 逆向 部分题解_第2张图片

在ida浏览A界面选定要查看的函数,按f5看到了伪代码, 于是点击字符串按R转化为其实际值

南邮 逆向 部分题解_第3张图片

南邮 逆向 部分题解_第4张图片

flag:

flag{Welcome_To_RE_World!}

 

ReadAsm2

南邮 逆向 部分题解_第5张图片

 

分析main函数 可以发现主要功能还是在于func函数中 于是我们仔细看func函数

南邮 逆向 部分题解_第6张图片

00000000004004e6<func>:;4004e6一列表示该指令对应的虚拟内存地址 55一列为该指令对应的计算机指令

4004e6:55push rbp ;入栈,将寄存器的值压入调用 bp栈中

4004e7:4889 e5 mov rbp,rsp;建立新栈帧,别掉函数栈帧栈底地址放入寄存器

4004ea:48897d e8 movQWORDPTR[rbp-0x18],rdi;对应main中input[]这时i=0 //[rbp-0x18] = input[0]

4004ee:8975 e4 movDWORDPTR[rbp-0x1c],esi;放入28 //[rbp-0x1c] = 28

4004f1: c745 fc 01000000movDWORDPTR[rbp-0x4],0x1;首先将0x1赋值给[rbp-0x4] //i = 1

4004f8: eb28jmp400522<func+0x3c>;接着跳转到400522的位置 //for(i=1;i<=28;i++) 下面以第一次过程为例

4004fa:8b45 fc moveax,DWORDPTR[rbp-0x4];将[rbp-0x4]的值赋给eax寄存器 //即令eax=i =1

4004fd:4863 d0 movsxd rdx,eax;将eax的值带符号扩展,并传送至rdx中 //即令rdx=eax =i =1

400500:488b45 e8 mov rax,QWORDPTR[rbp-0x18];将rax的值给input[0] //即令rax = input[0] =[rbp-0x18]

400504:4801 d0 add rax,rdx;将rdx的值加上rax再赋值给rax //即 rax=input[1] =i+input[0] =rdx+rax

400507:8b55 fc movedx,DWORDPTR[rbp-0x4];将[rbp-0x4]的值给edx //即令edx=i =1

40050a:4863 ca movsxd rcx,edx;将edx的值带符号扩展,并传送至rcx中 //即令rcx=i =1

40050d:488b55 e8 mov rdx,QWORDPTR[rbp-0x18];将[rbp-0x18]的值给rdx //即令rdx=[rbp-0x18] =input[0]

400511:4801 ca add rdx,rcx;将rcx的值加上rdx再赋值给rdx //即i++ rdx=input[1]

400514:0f b6 0amovzxecx,BYTEPTR[rdx];将rdx无符号扩展,并传送至ecx //即ecx=chr(rdx) =chr(input[0])

400517:8b55 fc movedx,DWORDPTR[rbp-0x4];edx = [rbp-0x4] //即edx=i =1

40051a:31 ca xoredx,ecx;将edx与ecx异或 //i^input[0]

40051c:8810movBYTEPTR[rax],dl;rax = dl

40051e:8345 fc 01addDWORDPTR[rbp-0x4],0x1;[rbp-0x4]++ //i++

400522:8b45 fc moveax,DWORDPTR[rbp-0x4];将[rbp-0x4]的值赋给eax寄存器 //eax = i

400525:3b45 e4 cmpeax,DWORDPTR[rbp-0x1c];将[rbp-0x1c]中的值与eax值比较第一次就是28

400528:7e d0 jle4004fa<func+0x14>;如果<=那么就跳到4004fa //if eax即i <=28跳到4004fa继续循环

40052a:90nop;空指令

40052b:5dpop rbp ;出栈

40052c: c3ret;ret相当于return

 

 

分析可得Python3代码:

 

 

a = [0x0, 0x67, 0x6e, 0x62, 0x63, 0x7e, 0x74, 0x62, 0x69, 0x6d,

0x55, 0x6a, 0x7f, 0x60, 0x51, 0x66, 0x63, 0x4e, 0x66, 0x7b,

0x71, 0x4a, 0x74, 0x76, 0x6b, 0x70, 0x79, 0x66 , 0x1c]

​​​​​​​s = ''

​​​​​​​for i in range(1,len(a)):

​​​​​​​s += chr(a[i]^i)

​​​​​​​​​​​​​​print (s)

运行结果如下:

南邮 逆向 部分题解_第7张图片

 

相应的汇编知识:

转自:https://www.cnblogs.com/Chesky/p/nuptzj_re_writeup.html

入栈,将寄存器的值压入调用 bp 栈中
建立新栈帧,别掉函数栈帧栈底地址放入寄存器

实现

 push   rbp
 mov    rbp,rsp

寄存器类型:

ax(accumulator): 可用于存放函数返回值
bp(base pointer): 用于存放执行中的函数对应的栈帧的栈底地址
sp(stack poinger): 用于存放执行中的函数对应的栈帧的栈顶地址
ip(instruction pointer): 指向当前执行指令的下一条指令

前缀加上 r 表示 64 位, e 表示 32 位,使用时表示该寄存器存储 xx 位的数据。

  • -word 表示字
    q 四字 d 双字
    dword qword
dword 2*16 =32 位
qword 4*16 = 64 位 
  • PTR 指针(pointer)
    没有寄存器名时, X ptr 指明内存单元的长度,X 在汇编指令中可以为word 或 byte 。

  • 内存地址
[rbp-0x18]
  • 涉及指令
1.movsxd 指令为扩展至零
将32位的寄存器和内存操作数符号扩展到64位的寄存器
2.逻辑异或运算指令 XOR 
XOR OPRD1,OPRD2 
实现两个操作数按位‘异或’(异为真,相同为假)运算,结果送至目的操作数中.
OPRD1<--OPRD1 XOR OPRD2
3.JLE
 小于等于时转移

flag:

flag{read_asm_is_the_basic}

 

MAZE

MAZE拖进winhex发现是elf文件,ida64打开,调出main函数,反编译:

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  signed __int64 v3; // rbx@4
  signed int v4; // eax@5
  bool v5; // bp@5
  bool v6; // al@8
  const char *v7; // rdi@19
  __int64 v9; // [sp+0h] [bp-28h]@1

  v9 = 0LL;
  puts("Input flag:");
  scanf("%s", &s1, 0LL);
  if ( strlen(&s1) != 24 || strncmp(&s1, "nctf{", 5uLL) || *(&byte_6010BF + 24) != 125 )
  {
LABEL_22:
    puts("Wrong flag!");
    exit(-1);
  }
  v3 = 5LL;
  if ( strlen(&s1) - 1 > 5 )
  {
    while ( 1 )
    {
      v4 = *(&s1 + v3);
      v5 = 0;
      if ( v4 > 78 )
      {
        v4 = (unsigned __int8)v4;
        if ( (unsigned __int8)v4 == 'O' )
        {
          v6 = sub_400650((_DWORD *)&v9 + 1);    //v6为v9的下一个字节 
          goto LABEL_14;
        }
        if ( v4 == 'o' )
        {
          v6 = sub_400660((int *)&v9 + 1);    //v6为v9的下一个字节
          goto LABEL_14;
        }
      }
      else
      {
        v4 = (unsigned __int8)v4;
        if ( (unsigned __int8)v4 == '.' )
        {
          v6 = sub_400670(&v9);         //v6为v9的本字节
          goto LABEL_14;
        }
        if ( v4 == '0' )
        {
          v6 = sub_400680((int *)&v9);    //v6为v9
LABEL_14:
          v5 = v6;
          goto LABEL_15;
        }
      }
LABEL_15:
      if ( !(unsigned __int8)sub_400690((__int64)asc_601060, SHIDWORD(v9), v9) )
        goto LABEL_22;
      if ( ++v3 >= strlen(&s1) - 1 )
      {
        if ( v5 )
          break;
LABEL_20:
        v7 = "Wrong flag!";
        goto LABEL_21;
      }
    }
  }
  if ( *(&asc_601060[8 * (signed int)v9] + SHIDWORD(v9)) != 35 )          ///v9为行数
    goto LABEL_20;
  v7 = "Congratulations!";
LABEL_21:
  puts(v7);
  return 0LL;
}

/////////SHIDWORD///////////////////查了一下IDA的宏定义 #define HIDWORD(x) (((_DWORD)&(x)+1))

太长了,简单看了一下,对输入的字符串限制了24的长度,保证以“nctf{”开头,“}”结尾。换成graph view:

南邮 逆向 部分题解_第8张图片

可以看到他根据判断是否为'.','0','o','O'来决定进行什么操作

bool __fastcall sub_400650(_DWORD *a1)//(_DWORD *)&v9 + 1
{
//为O(0x4f)的时候   

  int v1; // eax@1

  v1 = (*a1)--;
  return v1 > 0;
}

bool __fastcall sub_400660(int *a1)//(int *)&v9 + 1
{
///为o的时候
  int v1; // eax@1

  v1 = *a1 + 1;
  *a1 = v1;
  return v1 < 8;
}

bool __fastcall sub_400670(_DWORD *a1)//&v9
{
//为.的时候
  int v1; // eax@1

  v1 = (*a1)--;
  return v1 > 0;
}

bool __fastcall sub_400680(int *a1)//(int *)&v9
{
//为0(0x30)的时候
  int v1; // eax@1

  v1 = *a1 + 1;
  *a1 = v1;
  return v1 < 8;
}


南邮 逆向 部分题解_第9张图片

判断O为左移一位,o为右移一位,.为上移一位,0为下移一位。根据下图,判断出偏移为601060的地方放着我们要比较的东西,他依次把数据交给寄存器EDI,调用函数:

sub_400690 proc near
movsxd  rax, esi
add     rax, rdi
movsxd  rcx, edx
movzx   eax, byte ptr [rax+rcx*8]
cmp     eax, 20h
setz    cl
cmp     eax, 23h
setz    al
or      al, cl
retn
sub_400690 endp

MAZE这个题目就是迷宫了,上面的函数说明了在将EDI中的数与20h和23h比较,不符合就GG,来看看我们需要走的那个迷宫,就是地址为0000000000601060的HEX:

输入图片说明

整理一下得到8X8的矩阵:

南邮 逆向 部分题解_第10张图片

按照函数规则走一下

南邮 逆向 部分题解_第11张图片

将走的线路换成上诉的四个字符,得到o0oo00O000oooo..OO即为flag

flag:

nctf{o0oo00O000oooo..OO}

 

 

你可能感兴趣的:(南邮逆向wp,ctf)