HGAME 2024 WEEK1 WP

news2024/11/15 4:20:14

文章目录

    • WEB
      • ezHTTP
      • Bypass it
      • Select Courses
      • 2048*16
      • jhat
    • RE
      • ezASM
      • ezPYC
      • ezUPX
      • ezIDA
    • PWN
      • EzSignIn
    • CRYPTO
      • 奇怪的图片
      • ezRSA
      • ezMath
      • ezPRNG
    • MISC
      • SignIn
      • 来自星尘的问候
      • simple_attack
      • 希儿希儿希尔
      • 签到

放假比较闲,打打比赛
在这里插入图片描述

WEB

ezHTTP

来自vidar.club、UA要求阿巴阿巴阿巴、来自本地(提示不是XFF,其他的都试一下发现是X-Real-IP)、最后解jwt得到flag

在这里插入图片描述

Bypass it

有个注册按钮但是无法跳转过去,查看一下注释发现里面有个JavaScript写的alert('很抱歉,当前不允许注册');top.location.href='login.html'

那么禁用一下浏览器的js注册一个账号,再开启js即可,火狐浏览器的方法为
url框输入about:config搜索javascript.enabled,把true改成false即可

Select Courses

最迷惑的一集

在这里插入图片描述

然后想着里面有个full,源码里面还看到了is_full这些

在这里插入图片描述

接着就一直这样发包:

在这里插入图片描述

full还是1对吧,但是如果左边我故意让右边400几次,再发正常的包,多次重复这个步骤,莫名其妙full=0了

(例如下面这张图期间发了1次id=4+4,id=441,发了3次id=4)

在这里插入图片描述

复现不出来,纯看运气,拿当时出交flag时截的截图了

在这里插入图片描述

2048*16

卡死惹

有个index-_wkhdPNY.js,存的整个游戏的逻辑,大概率flag的输出在这里面

随便找个格式化一下https://willnode.github.io/deobfuscator/

在这里插入图片描述

盲猜flag被base64加密过,不过搜hga的base64字符串没搜到,继续往下翻

在这里插入图片描述

猜测这个可能跟flag有关,先保留

在这里插入图片描述

找到获胜的逻辑,会执行s0(n(439), "V+g5LpoEej/fy0nPNivz9SswHIhGaDOmU8CuXb72dB1xYMrZFRAl=QcTq6JkWK4t3")

随便打开个网页,在控制台把整个js输入进去

在这里插入图片描述

然后alert一下s0(n(439), "V+g5LpoEej/fy0nPNivz9SswHIhGaDOmU8CuXb72dB1xYMrZFRAl=QcTq6JkWK4t3")

在这里插入图片描述

jhat

之前问gpt问了老半天,直到hint3已出现就恍然大悟怎么问了

在这里插入图片描述

select new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream("/flag"))).readLine()

在这里插入图片描述

接着问了一下GPT,读取根目录:select java.util.Arrays.toString(new java.io.File("/").list())

在这里插入图片描述

RE

ezASM

在这里插入图片描述

与0x22异或即可

在这里插入图片描述

ezPYC

刚开始用着几年前一直用的pyinstxtractor发现就是逆不出pyc头,才发现这玩意早更新了

然后找个在线的pyc逆一下即可

flag = [
    87,
    75,
    71,
    69,
    83,
    121,
    83,
    125,
    117,
    106,
    108,
    106,
    94,
    80,
    48,
    114,
    100,
    112,
    112,
    55,
    94,
    51,
    112,
    91,
    48,
    108,
    119,
    97,
    115,
    49,
    112,
    112,
    48,
    108,
    100,
    37,
    124,
    2]
c = [
    1,
    2,
    3,
    4]
#后略

一眼xor

在这里插入图片描述

ezUPX

upx -d ezUPX

然后IDA打开即可

在这里插入图片描述

在这里插入图片描述

xor 0x32

在这里插入图片描述

VIDAR{Wow!Y0u_kn0w_4_l1ttl3_0f_UPX!}

ezIDA

IDA直接打开就能看到

PWN

EzSignIn

nc即可

CRYPTO

奇怪的图片

不是很懂密码为什么会放这个题,感觉还是考的misc,要说密码的话总感觉有点像OTP的样子

简单分析函数

import time

from PIL import Image, ImageDraw, ImageFont
import threading
import random
import secrets


flag = "hgame{fake_flag}"

#生成随机RGB图片
def generate_random_image(width, height):
    image = Image.new("RGB", (width, height), "white")
    pixels = image.load()
    for x in range(width):
        for y in range(height):
            red = random.randint(0, 255)
            green = random.randint(0, 255)
            blue = random.randint(0, 255)
            pixels[x, y] = (red, green, blue)
    return image

#图像上画flag
def draw_text(image, width, height, token):
    font_size = random.randint(16, 40)
    font = ImageFont.truetype("arial.ttf", font_size)
    text_color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
    x = random.randint(0, width - font_size * len(token))
    y = random.randint(0, height - font_size)
    draw = ImageDraw.Draw(image)
    draw.text((x, y), token, font=font, fill=text_color)
    return image

#异或两张图RGB
def xor_images(image1, image2):
    if image1.size != image2.size:
        raise ValueError("Images must have the same dimensions.")
    xor_image = Image.new("RGB", image1.size)
    pixels1 = image1.load()
    pixels2 = image2.load()
    xor_pixels = xor_image.load()
    for x in range(image1.size[0]):
        for y in range(image1.size[1]):
            r1, g1, b1 = pixels1[x, y]
            r2, g2, b2 = pixels2[x, y]
            xor_pixels[x, y] = (r1 ^ r2, g1 ^ g2, b1 ^ b2)
    return xor_image

#生成与随机token当文件名
def generate_unique_strings(n, length):
    unique_strings = set()
    while len(unique_strings) < n:
        random_string = secrets.token_hex(length // 2)
        unique_strings.add(random_string)
    return list(unique_strings)

random_strings = generate_unique_strings(len(flag), 8)


current_image = generate_random_image(120, 80)
key_image = generate_random_image(120, 80)

def random_time(image, name):
    time.sleep(random.random())
    image.save(".\\png_out\\{}.png".format(name))

for i in range(len(flag)):
    current_image = draw_text(current_image, 120, 80, flag[i])
    threading.Thread(target=random_time, args=(xor_images(current_image, key_image), random_strings[i])).start()

简单看了一下,生成了一个随机RGB的image和一个key_image,然后在image上面生成一个flag的其中一个字符就异或一下一直到生成完。能够发现current_image是用的同一张,意思是生成了字符之后还会在上面生成,就会产生覆盖(不过不要紧)

简单来说,就是

key^a1 = a2
key^b1 = b2

a2^b2 = a1^b1
背景都是相同的,那么a1^b1就是异或不同的字符

基于这一点,我想到如果我选中的图是第一张图或者最后一张图,那么用这张图片去异或其他图片,得到的信息是绝对递增的,不会出现信息个数相同的情况(即假设全为flag{123}选中的为f,再往后异或会出现f^fl = l,f^fla = la……;反之}^3} = 3,}^23} = 23)

因此尝试爆破

from PIL import Image, ImageDraw, ImageFont


def xor_images(image1, image2):
    if image1.size != image2.size:
        raise ValueError("Images must have the same dimensions.")
    xor_image = Image.new("RGB", image1.size)
    pixels1 = image1.load()
    pixels2 = image2.load()
    xor_pixels = xor_image.load()
    for x in range(image1.size[0]):
        for y in range(image1.size[1]):
            r1, g1, b1 = pixels1[x, y]
            r2, g2, b2 = pixels2[x, y]
            xor_pixels[x, y] = (r1 ^ r2, g1 ^ g2, b1 ^ b2)
    return xor_image

import os
DL = os.listdir('./')
NDL = [file for file in DL if ".png" in file]
print(NDL)
print(len(NDL))
for j in range(len(NDL)):
    image1 = Image.open(NDL[j])
    dr = NDL[j].split(".png")[0]
    os.mkdir(f'../{dr}')
    for i in range(len(NDL)):
        image2 = Image.open(NDL[i])
        image3 = xor_images(image1,image2)
        image3.save(f'../{dr}/{i}.png')
        image3.close()
        image2.close()

这里获得了很多文件夹,当我看到18ef202a的时候发觉不简单,有一张单独出现的{

在这里插入图片描述

注意到出现{的个数正好为5个,说明这张原图上面写的字符是hgame{,那么后面按照顺序递增就是flag的正向顺序

最后排序得到hgame{1adf_17eb_803c}

ezRSA

观察到leak1和leak2是

leak1=pow(p,q,n)
leak2=pow(q,p,n)

不是很懂密码,所以只能百度这个了,找到一个用了leak1=pow(p,q,n)的题https://www.cnblogs.com/U-L-G-A-N-O-Y/articles/17866487.html

在这里插入图片描述

在这里插入图片描述

可知leak1和leak2其实就是p和q,写常规解RSA即可

import gmpy2
import binascii

e = 65537
p = 149127170073611271968182576751290331559018441805725310426095412837589227670757540743929865853650399839102838431507200744724939659463200158012469676979987696419050900842798225665861812331113632892438742724202916416060266581590169063867688299288985734104127632232175657352697898383441323477450658179727728908669
q = 116122992714670915381309916967490436489020001172880644167179915467021794892927977272080596641785569119134259037522388335198043152206150259103485574558816424740204736215551933482583941959994625356581201054534529395781744338631021423703171146456663432955843598548122593308782245220792018716508538497402576709461
c=10529481867532520034258056773864074017027019578041866245400647840230251661652999709715919620810933437191661180003295923273655675729588558899592524235622728816065501918076120812236580344991140980991532347991252705288633014913479970610056845543523591324177567061948922552275235486615514913932125436543991642607028689762693617305246716492783116813070355512606971626645594961850567586340389705821314842096465631886812281289843132258131809773797777049358789182212570606252509790830994263132020094153646296793522975632191912463919898988349282284972919932761952603379733234575351624039162440021940592552768579639977713099971
n = p*q

L = (p-1)*(q-1)
d = gmpy2.invert(e,L)
m = gmpy2.powmod(c,d,n)

print(binascii.unhexlify(hex(m)[2:]))
#hgame{F3rmat_l1tt1e_the0rem_is_th3_bas1s}

ezMath

不懂crypto,搜一下特征assert x**2 - D * y**2 == 1

https://www.wxjk.net/other/23395136.html

在这里插入图片描述

#sage
numTry = 1500
def solve_pell(N, numTry):
    cf = continued_fraction(sqrt(N))
    for i in range(numTry):
        denom = cf.denominator(i)
        numer = cf.numerator(i)
        if numer^2 - N * denom^2 == 1:
            return numer, denom
    return None, None

x,y = solve_pell(114514,numTry)
print(y)

在这里插入图片描述

得到

9037815138660369922198555785216162916412331641365948545459353586895717702576049626533527779108680

解一下就行

from Crypto.Cipher import AES
from libnum import n2s as long_to_bytes
def pad(x):
    return x+b'\x00'*(16-len(x)%16)
y = 9037815138660369922198555785216162916412331641365948545459353586895717702576049626533527779108680

key_bytes = long_to_bytes(y)
key_padded = pad(key_bytes)[:16]

enc = b"\xce\xf1\x94\x84\xe9m\x88\x04\xcb\x9ad\x9e\x08b\xbf\x8b\xd3\r\xe2\x81\x17g\x9c\xd7\x10\x19\x1a\xa6\xc3\x9d\xde\xe7\xe0h\xed/\x00\x95tz)1\\\t8:\xb1,U\xfe\xdec\xf2h\xab`\xe5'\x93\xf8\xde\xb2\x9a\x9a"

cipher = AES.new(key_padded, AES.MODE_ECB)
decrypted_flag = cipher.decrypt(enc)

print(decrypted_flag)
#b'hgame{G0od!_Yo3_k1ow_C0ntinued_Fra3ti0ns!!!!!!!}\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

ezPRNG

不是很懂密码学,我只知道lfsr和伪随机数那个库,但是改一改就不是很会了,这个题我选择的是

c语言多线程爆破(爆破完约6小时,针对此题耗时约2小时)

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <pthread.h>

#define NUM_THREADS 8  // CPU线程
#define SEARCH_SPACE 4294967295U

uint32_t PRNG(uint32_t R, uint32_t mask) {
    uint32_t nextR = (R << 1) & 0xffffffff;
    uint32_t i = (R & mask) & 0xffffffff;
    uint32_t nextbit = 0;
    while (i != 0) {
        nextbit ^= (i % 2);
        i = i / 2;
    }
    nextR ^= nextbit;
    return nextR;
}

void *search_thread(void *arg) {
    int thread_id = *((int *)arg);
    uint32_t mask = 0b10001001000010000100010010001001;
    char* outputs[4] = {
        "1111110110111011110000101011010001000111111001111110100101000011110111",
        "0010000000001010111100001100011101111101111000100100111010101110010110",
        "1110110110010001011100111110111110111001111101010011001111100100001000",
        "0001101010101010100001001001100010000101010100001010001000100011101100"
    };
    char buffer[71];

    uint32_t start = thread_id * (SEARCH_SPACE / NUM_THREADS);
    uint32_t end = (thread_id == NUM_THREADS - 1) ? SEARCH_SPACE : (thread_id + 1) * (SEARCH_SPACE / NUM_THREADS);

    for (int i = 0; i < 4; i++) {
        for (uint32_t R = start; R <= end; R++) {
            uint32_t currentR = R;
            for (int j = 0; j < 70; j++) {
                currentR = PRNG(currentR, mask);
                buffer[j] = (currentR & 1) + '0';
            }
            buffer[70] = '\0';

            if (strncmp(buffer, outputs[i], 70) == 0) {
                printf("Found matching R: %08x in thread %d\n", R, thread_id);
                break;
            }
			    if (R % 100000000 == 0) {
                printf("Progress: %u\n", R);}
        }
    }

    return NULL;
}

int main() {
    pthread_t threads[NUM_THREADS];
    int thread_ids[NUM_THREADS];

    for (int i = 0; i < NUM_THREADS; i++) {
        thread_ids[i] = i;
        pthread_create(&threads[i], NULL, search_thread, (void *)&thread_ids[i]);
    }

    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }

    printf("Search completed.\n");
    return 0;
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

总之最后得到flag:hgame{fbbbee82-3f43-4f91-9337-907880e4191a}

MISC

SignIn

笑鼠了,刚开赛太着急看换个方式签到,以为说的是满足'hgame\{[A-Z_]+\}'就行,过了半分多钟才发现不对旁边有个附件。

发到手机上从充电口网上看就行了

hgame{WOW_GREAT_YOU_SEE_IT_WONDERFUL}

来自星尘的问候

当时stegbreak没爆出来就没去单独试steghide了,后来单独试了发现是steghide,不知道stegbreak咋回事,下次还是stegseek吧。

密码123456,然后图片进行谷歌搜图

在这里插入图片描述

搜字母表https://www.bilibili.com/read/cv14514692/

手动转换一下得到hgame{wel??me!}

没找到问号,试了一下welcome不对,感觉是数字但是一下子没找到,去搜leet发现字母c没有对应的数字表示,就试了下hgame{welc0me!},正确

simple_attack

明文攻击,不过第一次用winrar压缩发现不能被攻击,我猜出题人又是用的bandzip,用bandzip果不其然能被攻击,而且为什么不用store;还有为什么不用winrar,感觉好像bandzip跟其他压缩软件挺格格不入的

在这里插入图片描述

解压出来的photo直接浏览器输入即可自动转base64的图片

在这里插入图片描述

希儿希儿希尔

一眼希尔密码,文件尾找到密文,看图片就是恢复高宽了,百度找一个爆破CRC的即可

这个代码直接换原新的图片

import binascii
import struct
import sys
file = input("图片地址:")
fr = open(file,'rb').read()
data: bytearray = bytearray(fr[0x0c:0x1d])
crc32key = eval('0x'+str(binascii.b2a_hex(fr[0x1d:0x21]))[2:-1])
n = 4095
for w in range(n):
    width = bytearray(struct.pack('>i', w))
    for h in range(n):
        height = bytearray(struct.pack('>i', h))
        for x in range(4):
            data[x+4] = width[x]
            data[x+8] = height[x]
        crc32result = binascii.crc32(data) & 0xffffffff
        if crc32result == crc32key:
            print(width,height)
            newpic = bytearray(fr)
            for x in range(4):
                newpic[x+16] = width[x]
                newpic[x+20] = height[x]
            fw = open(file+'.png','wb')
            fw.write(newpic)
            fw.close
            file.close()

得到的图片存在LSB,里面是key

在这里插入图片描述

在这里插入图片描述

hgame{DISAPPEARINTHESEAOFBUTTERFLY}

签到

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1436644.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

zlib交叉编译(rv1126)

目录 1.下载 2.解压 3.配置 4.编译 1.下载 1)下载地址 zlib Home Site 2)下载tar.gz版本 下载该版本。 2.解压 1)解压到某个文件夹

使用Qt创建项目 Qt中输出内容到控制台 设置窗口大小和窗口标题 Qt查看说明文档

按windows键&#xff0c;找到Qt Creator &#xff0c;打开 一.创建带模板的项目 新建项目 设置项目路径QMainWindow是带工具栏的窗口。 QWidget是无工具栏的窗口。 QDuakig是对话框窗口。创建好的项目如下&#xff1a; #include "widget.h"// 构造函数&#xff…

SpringBoot整合Knife4j接口文档生成工具

一个好的项目&#xff0c;接口文档是非常重要的&#xff0c;除了能帮助前端和后端开发人员更快地协作完成开发任务&#xff0c;接口文档还能用来生成资源权限&#xff0c;对权限访问控制的实现有很大的帮助。 这篇文章介绍一下企业中常用的接口文档工具Knife4j&#xff08;基于…

Springboot集成rocketmq快速入门demo

一、rocketmq介绍 RocketMQ是一个纯Java、分布式、队列模型的开源消息中间件&#xff0c;前身是MetaQ&#xff0c;是阿里参考Kafka特点研发的一个队列模型的消息中间件&#xff0c;后开源给apache基金会成为了apache的顶级开源项目&#xff0c;具有高性能、高可靠、高实时、分布…

PyTorch 2.2 中文官方教程(十九)

使用 RPC 进行分布式管道并行 原文&#xff1a;pytorch.org/tutorials/intermediate/dist_pipeline_parallel_tutorial.html 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 作者&#xff1a;Shen Li 注意 在github中查看并编辑本教程。 先决条件&#xff1a; PyTorc…

JVM 性能调优 - 四种引用(4)

为什么会有四种引用 我们先回顾下在 Java 虚拟机内存体系(1) 中提到了的垃圾回收算法 1、引用计数法 原理:给对象添加一个引用计数器,每当有一个地方引用它,计数器的值就加一。每当有一个引用失效,计数器的值就减一。当计数器值为零时,这个对象被认为没有其他对象引用,…

专业排版设计软件:QuarkXPress 2024 for mac中文激活版

QuarkXPress 2024 for Mac是一款功能强大、易于使用、高质量输出的专业排版软件。无论您是出版业的专家还是初学者&#xff0c;都可以通过QuarkXPress 2024轻松创建出令人惊叹的出版物。 软件下载&#xff1a;QuarkXPress 2024 for mac中文激活版下载 QuarkXPress 2023 for Mac…

mvn常见报错:Failed to read artifact descriptor for 解决

问题&#xff1a; mvn打包时报错&#xff1a;Failed to read artifact descriptor for 产生原因&#xff1a; 项目打包时所需的依赖包不存在本地仓库&#xff0c;或本地仓库文件存在问题。 解决方法&#xff1a; 检查仓库可用性&#xff1a; 确保在Maven设置或pom.xml中指定…

居然在Web上就可以体验下MacOS啦?

发现一款宝藏项目 MacOS &#xff0c;在Web上打造一款原汁原味的 MacOS系统&#xff0c;不同于以外的仿操作系统的web应用&#xff0c;该应用底层基于 HTML5的 FileSystem 和 IndexedDB 构建了文件系统&#xff0c;理论上可以基于这套系统实现任何的上层应用。作者还制定了可以…

nacos越权漏洞复现

1.低版本(nacos<1.4.1)默认白名单UA 开启鉴权功能后&#xff0c;服务端之间的请求也会通过鉴权系统的影响。考虑到服务端之间的通信应该是可信的&#xff0c;因此在1.2~1.4.0版本期间&#xff0c;通过User-Agent中是否包含Nacos-Server来进行判断请求是否来自其他服务端。 但…

程序员为什么不喜欢关电脑?

目录 标题&#xff1a;程序员为何乐见电脑长时间处于关闭状态&#xff1f; 引言&#xff1a; 一、思维的延续性&#xff1a; 二、环境的连续性&#xff1a; 三、长时间开机的原因&#xff1a; 四、恢复成本的考量&#xff1a; 结论&#xff1a; 特别的&#xff1a; 不是…

Vue3快速上手(二)VSCode官方推荐插件安装及配置

一、VSCode官方插件安装&#xff0c;如下图2款插件 在用vite创建的程序里&#xff0c;提示提安装推荐的插件了&#xff0c;如下图&#xff1a; 二、配置 在设置-扩展里找到Volar插件&#xff0c;将Dot Value勾选上。这样在ref()修改变量时&#xff0c;会自动填充.value,无需…

电力负荷预测 | 基于ARIMA的电力负荷预测(Python)

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 电力负荷预测 | 基于ARIMA的电力负荷预测(Python) 源码设计 #------------

第6节、T型加减速转动【51单片机+L298N步进电机系列教程】

↑↑↑点击上方【目录】&#xff0c;查看本系列全部文章 摘要&#xff1a;本章介绍步进电机T型加减速的控制方法&#xff0c;分三个小节&#xff0c;本小节主要内容为该控制方法的推导与计算。目前各平台对该控制方法介绍的文章目前较多&#xff0c;但部分关键参数并未给出推导…

图解GPT2

GPT是一种Transformer Decoder架构&#xff0c;Decoder通过自回归方式生成下一个词&#xff0c;所以擅长文本生成任务。 本文将图解GPT2&#xff0c;本系列还有图解Tokenization&#xff0c;Word2Vec&#xff0c;Transformer&#xff0c;Bert。 这篇文章主要来自下面这篇博客。…

【C++】内存管理深入解析

目录 1. 内存的五大区域1.1 栈区&#xff08;Stack&#xff09;1.2 堆区&#xff08;Heap&#xff09;1.3 全局/静态存储区1.4 常量存储区1.5 代码区 2. 回顾c语言的动态内存管理2.1 malloc/calloc/realloc2.2 free 3. C中的新旧对话3.1 new3.2 delete 4. new/delete的实现原理…

IDEA生成可执行jar包

1. 进入需要打包的项目&#xff0c;选择 最上方菜单栏的 File → Project Structure 2. 选择 左侧菜单栏 Artifacts → 加号 → JAR → from modules with dependencies 3. 选择入口类 Main Class&#xff08;点击文件夹图标可以快速选择&#xff09;&#xff0c;点击 OK&#…

(四)elasticsearch 源码之索引流程分析

https://www.cnblogs.com/darcy-yuan/p/17024341.html 1.概览 前面我们讨论了es是如何启动&#xff0c;本文研究下es是如何索引文档的。 下面是启动流程图&#xff0c;我们按照流程图的顺序依次描述。 其中主要类的关系如下: 2. 索引流程 (primary) 我们用postman发送请求&…

【漏洞复现】EPON上行A8-C政企网关未授权下载漏洞

Nx01 产品简介 EPON上行A8-C政企网关是一款终端产品&#xff0c;提供企业网络解决方案。 Nx02 漏洞描述 EPON上行A8-C政企网关配置文件未授权下载漏洞&#xff0c;攻击者在未授权状态下下载配置文件&#xff0c;获取配置文件内敏感信息。 Nx03 产品主页 fofa-query: "Z…

龙宝宝头像怎么做?分享3个AI生成工具!

龙宝宝头像怎么做&#xff1f;分享3个AI生成工具&#xff01; 在这个数字化时代&#xff0c;社交媒体已成为我们展示个性和表达自我的重要舞台。龙宝宝头像不仅有传统的中国龙形象&#xff0c;还有各种创意十足的卡通头像。然而&#xff0c;设计一个理想的头像并非易事&#x…