collision - pwnable
1. 连接服务器&获取题目
我们先用ssh链接上pwnable的服务器获取题目。在终端输入ssh col@pwnable.kr -p2222
,出现提示后输入密码guest
查看目录下有的文件以及文件权限ls -l
这题与fd给出文件一样,不能直接读取flag,给出源代码;
2. 运行程序、查看文件类型、保护措施
我们先运行一下
直接运行提示需要一个passcode;给出随机密码后提示密码长度应该为20个字节;传入20个字节的参数提示密码错误;
查看文件的基本信息:32位动态链接的ELF
查看文件的保存措施:
3.分析源码
因为题目有给出源码,所以就不需要将程序丢到IDA中分析了。
查看源码:cat col.c
#include <stdio.h>
#include <string.h>
unsigned long hashcode = 0x21DD09EC;
unsigned long check_password(const char* p){
int* ip = (int*)p;
int i;
int res=0;
for(i=0; i<5; i++){
res += ip[i];
}
return res;
}
int main(int argc, char* argv[]){
if(argc<2){
printf("usage : %s [passcode]\n", argv[0]);
return 0;
}
if(strlen(argv[1]) != 20){
printf("passcode length should be 20 bytes\n");
return 0;
}
if(hashcode == check_password( argv[1] )){
system("/bin/cat flag");
return 0;
}
else
printf("wrong passcode.\n");
return 0;
}
- 程序需要提供参数,否则报错usage : %s [passcode]
- 提供的参数长度需要为是20个字节,否则报错passcode length should be 20 bytes
- 调用check_password函数对参数进行处理,如果返回值等于全局变量hashcode,则输出flag内容
- 传入check_password的是一个不可变字符串指针,然后将其强制转变为整数型指针;之后进行一共循环5次的for循环累加;p长度为20个字节,转换后ip长度依然是20个字节,结合前面查看文件类型,可以推出一共ip有5个整数,每个整数长度为4个字节。
我们开始回推参数应该是多少:首先需要check_password的返回值等于hashcode,也就是说ip中的5个整数和等于hashcode;那么就要求输入的参数为5个整数的对应字符串收尾相接地组成的长度为20个字节的长字符串。
按照我们的分析,hashcode的结构应该是:hashcode = A + B + C + D + E
;(字符之间可以相等)
这就意味答案有很多种,那先来说说我第一时间想出来的解法:
hashcode = hashcode + 0 + 0 +0 + 0
但这个参数实际被不能达到我们的目的。我们先来看看设想参数转换为字符串包含什么东西:\xec\t\xdd!\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
转换之后会出现感叹号!
,作为参数输入时会被系统认为是一条命令,系统报错找不到这条命令
如果尝试在!
前面加上转义符\
,长度则变为了21字节,程序报错长度不对
我也不知道怎么解决,欢迎大佬指教
-
那么就试试第二种办法
hashcode = A + B +B + B + B
,为了避免出现!
,注意避免选用字符串中带 ! 的整数。hashcode = 0x19548164 + 0x2222222*4
;这两个数符合条件,因此得出参数应该d\x81T\x19"""\x02"""\x02"""\x02"""\x02
那我们直接在服务器中生成参数,并调用程序:(复制粘贴输入程序报错长度不对)
python2#命令行中运行python2 #python交互环境↓ from pwn import * argc = p32(0x19548164) + p32(0x2222222)*4#生成参数 col = process(['./col',argc])#载入程序并传入参数 print col.recvline()#打印flag内容
4.总结
-
参数中含有!,参数会被linux系统当做命令
-
pwn process载入带有参数的程序写法:
col = process(['./col',argc])