之前学过一点关于pwn,不过总是断断续续,学一点就停止了,这次准备好好学一下。推荐一个网站这是个练习pwn的很好的网站
FD
先连上去
查看fd.c文件
main函数中:argc是命令行参数个数,char *argv[]是指所有命令行参数,char *envp[]是环境变量(argv[1]位置处存放的是命令行输入的第一个参数)
atoi函数的作用是把字符转化为int型数据。 命令行读入的参数默认是字符型(如:atio(10)=‘10’)
ssize_t read(int fd,void * buf,size_t count);
函数说明
read()会参数fd所有的文件传送count个字节到buf指针所指的内存中。若参数count为0,则read )不会有作用并返回0返回值为实际读取到的字节数,如果返回0,表示已到达文件尾或是无可读取的数据,此外文件读写位置会随读取到的字节移动。
整数值 名称 < unistd.h > 符号常量[1] < stdio.h > 文件流[2]
0 标准输入 STDIN_FILENO 标准输入
1 标准输出 STDOUT_FILENO 标准输出
2 标准错误 STDERR_FILENO 标准错误
那么我们只要控制了FD的值为标准输入,那么buf中的值就可以用我们的键盘输入了,
目标是使FD为0,那么我们传进去的第一个参数就是为0x1234,即十进制的4660
这里要填十进制因为天0x1234中的0x它会读成字符的,然后把后面的字符变成10进制
collision
#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;
}
int* ip = (int*)p;
这里对p进行了一次强制转化,从原本读出来的char转化为了int
char占一个字节,8个比特。int占4个字节,32个比特。
hashcode == check_password( argv[1] )实现了一个累加
这里需要构造一个a+b=0x21DD09EC
for(i=0; i<5; i++){
res += ip[i];
}
实际上就是把5*4=20个字符每4个分成一组累加。
0x1DD905E8+0x01010101*4=0x21DD09EC 我这里用01010101来构造
python -c “print ‘\xe8\x05\xd9\x1d’+16*’\x01’”|xargs ./col因为是小端机器需要反序,xargs可以把数据当作命令行参数传给制定的程序。