缅甸边境诈骗园区–军阀混战的产物

从寂静的小镇到整座城市,缅甸边境的一大片土地已经成为了跨国犯罪集团的中心,这些集团强迫人们进行大规模的网络诈骗犯罪活动,每年诈骗金额高达数万亿美元。这些诈骗中心在当地迅速蔓延,把人当作商品一样进行贩卖、强行关押、实施其他侵犯人权的行为,并受其胁迫在全球范围内实施诈骗,而缅泰边境的妙瓦底地区正是世界上诈骗中心最集中的地区之一。由于缅甸军政府、叛乱组织和地区军阀之间分裂的地缘政治格局,助长了这些犯罪集团的扩张,从小型的林间工棚到大型的城市院落,由诈骗集团产生的巨额收入支持着他们的日常活动并为缅甸军政府的暴行提供大量资金。

image

尽管缅甸军政府公开反对,但2024年的手机地理定位数据显示,妙瓦底诈骗中心与首都内比都,以及不同诈骗中心之间的频繁流动,揭示了潜在的犯罪聚集区域。具体情况如下:

  • 这些设备经常在诈骗园区(如水沟谷和KK园区)与首都的政府大楼之间频繁出现,表明有组织犯罪与缅甸军政权之间存在某种联系。
  • 这些设备在隶属于不同犯罪集团的诈骗园区(如东美园区和泰昌园区)之间流通,表明各个犯罪集团之间也有在进行“合作与协商”。

image

背景

当地时间2021年2月1日凌晨,缅甸发生军事政变,国家权力被移交给国防军总司令敏昂莱,随后几年间,缅甸军政府失去了对大片地区的控制权,导致犯罪集团得以扩大活动范围。这些组织与原缅甸军政府下属、索奇督上校领导的克伦民族军 (KNA)、民主克伦佛教军(DKBA)等其他武装组织以及各地区军阀合作,将泰缅边境的一片地带变成了世界上诈骗中心最集中的地方之一。2017年,索奇督上校与柬埔寨籍华裔佘智江领导的亚太国际控股集团合作,在佘智江支付470万美元的首付款后,开始在水沟谷开发亚太新城。此外,与14K组织头目尹国驹领导的东美集团还达成了一项开发赛西港的协议。

image

当地武装组织正是通过向水沟谷等犯罪园区的赌博和电诈企业提供了土地和安全保障获得收入。

这些诈骗中心的出现,很大一部分原因是东南亚地区在博彩领域的法律约束不够严格,大量的犯罪组织受东南亚较为宽松的法律环境所吸引,同时为了应对中国对跨境赌博和洗钱的严苛打击态势,在赌场和酒店方面投入巨资,吸引数百万游客前往该地区。然而,新冠疫情的爆发,导致当地旅游业崩溃,迫使这些组织将赌场业务多元化,实施诈骗活动,吸引来自世界各地的工作人员,强迫他们参与针对全球受害者的网络诈骗。

image

image

这些中心在掸邦(与中国、老挝和泰国接壤)和克伦邦(与泰国接壤)犯罪行为最为猖獗,当地法治意识淡薄,缺乏管理,缅甸军政府与叛乱组织之间的冲突造就了一种当地无法无天的社会环境。掸邦北部大部分地区被叛军控制,克伦民族联盟 (KNU) 及其武装派别克伦民族解放军 (KNLA) 在克伦邦割据一方。2023年,缅甸北部地区开始严厉打击网络犯罪。打击行动始于佤邦,随后果敢边防军被击败,网络犯罪遭受重创,数万名中国公民遣返回中国,而诈骗中心也被迫搬迁到妙瓦底周边。2025 年 2 月,中国和泰国与缅甸军政府合作,针对缅北犯罪中心展开打击,泰国切断了与缅甸边境地区的电力供应。

尽管缅甸军政府公开谴责并打击这些诈骗网络,但它们之间存在着共生关系。为了换取默许和安全保护,这些诈骗中心会将部分收入输送给克伦民族军。有消息称,克伦民族军与缅甸军政府共享诈骗中心收入,而敏昂莱则与克伦邦和掸邦的主要诈骗园区幕后老板保持联系。

园区

image

KK园区

目前,它由两个主要区域组成,通常被称为KK园区1号和KK园区2号。

2024年,区块链分析公司Chainalysis的一项调查发现,仅在KK园区内运营的一家诈骗集团在不到两年的时间里就从受害者手中骗取了超过1亿美元。考虑到该地区的犯罪团伙数量,估计实际数字要高出数十倍。

2024年2月至12月期间,KK园区1号和KK园区2号内新建了20多座建筑,连接两地的大片区域也已清理完毕,准备建造新建筑,卫星图像中可见多处地基。这两个区域的每日夜间辐射亮度数据显示,自2022年年中以来,辐射亮度迅速上升。与克伦邦首府帕安的夜间辐射亮度相比,这一增长尤为明显,帕安近年来的夜间辐射亮度实际上略有下降。

image

image

亚太新城

image

尽管相距 1000 公里,两个大型土地开发项目(一个在缅甸的克伦邦,另一个在柬埔寨的长湾)却有着惊人的相似之处:这两个项目都占地数千公顷,并计划建设机场、酒店和赌场;它们都位于尚待开发的角落;它们都被指控与网络赌博和其他非法活动有关,并且都被误认为是国有企业。

这两个项目都与同一位华裔商人有关:佘志江。

水沟谷是妙瓦底乡北部的一座城市,主要由亚太国际控股集团(亚太)建设。亚太是一家在香港注册的公司,其前董事长是柬埔寨华裔国民佘志江。佘志江目前在曼谷监狱等待引渡回中国,他被指控在东南亚经营非法赌博业务。2016 年,佘志江与索奇督达成协议,由亚太集团将瑞谷口从一个小村庄改造成一个度假城市,并受到克伦民族军的保护。项目于 2018 年获得投资项目批准。亚太集团的建设超出了其投资许可的限制,并在赌场在缅甸合法化之前就开始运营,引起了全国民主联盟政府的审查。尽管佘志江经常被描述为中国人,但他最初在缅甸亚太的公司记录中使用的名字是 Tang Kriang Kai(后来改为 She Zhi Jiang),并且他的国籍是柬埔寨人。柬埔寨政府文件显示,2017 年 1 月,王室下令授予佘志江公民身份,名字为 Tang Kriang Kai,而不到三周后,他就在缅甸投资与公司管理局注册了缅甸亚太公司。2022年在泰国因国际通缉令被捕。克伦边防军仍然忠于佘志江,2024年,齐图为他组织了一场祈祷仪式。

image

数据调查

调查追踪了 2024 年 1 月至 12 月期间检测到的符合以下条件的设备移动情况:

  • 在妙瓦底周边的四个已知诈骗中心之一至少检测到一次此设备,并且在内比都政府部门辖区及其周边政府部门住宅区至少检测到一次此设备。共发现7台符合此标准的设备。
  • 在妙瓦底江周边已知的四个诈骗中心位置中,至少有两个位置且至少检测到一次设备,共计213 台设备符合此标准,泰昌园区只有1个设备符合此标准。2024 年,符合此标准的设备有109台来自东美园区。

我们将这些限制访问地点之间的移动可以理解为一个更广泛的网络或行动角色的潜在迹象,将这些原本独立的站点连接起来,这些连线表明它们之间存在着十分紧密的关联。

image

有 6 个设备,暂定为 A、B、C、D、E 和 F ,在水沟谷和内比都的政府部门之间频繁移动:

  • 设备A:于2024年6月16日在内比都的南乌寺(Nan Oo Pagoda)被发现,该地点紧邻联邦议会(缅甸立法机构)。这表明该设备所有者可以进入受严密管辖的政府区域,因为该佛塔的建筑群正位于联邦议会的内部区域。
  • 设备B:多次造访缅甸外交部、多个部委办公楼和卫生部。该设备还曾造访水沟谷郊外一处不明建筑,该建筑距离自由水上乐园(亚太集团旗下企业)不到一公里,以及谷歌地图上标记为“拟建工业区”的约 76 英亩空地。根据卫星图像,该空地在 2024 年 2 月至 12 月期间遭到砍伐。
  • 设备C:曾出现在内比都的交通运输部和部长官邸,还拜访了疑似索奇督的住所。该设备所有者常驻在仰光,然而,该设备在7月份访问了内比都和水沟谷之后,定期访问内比都。根据这些行为分析,该设备所有者很可能拥有进入缅甸军政府管理区域的权限。
  • 在访问其他地区之后,2024 年 8 月在水沟谷发现了 D、E 和 F设备。

    • 设备D:在抵达水沟谷前约两周曾到访自然资源与环境部,并在约两周后在能源部被探查到,表明它可能在各个部门之间往返。
    • 设备E:在抵达水沟谷前,在内比都经历了一系列活动:在商务部、内比都农村公路发展部和民族事务部均被发现。
    • 设备F在缅甸中央银行、交通通讯部、体育与青年事务部以及商务部均有出现。值得注意的是,据报道,缅甸中央银行是帮助缅甸军政府逃避国际制裁的主要参与者。

image

设备

设备 A

  • 2024年7月13日至7月17日,A设备在水沟谷(Shwe Kokko)被发现。该设备主要停留在一个不起眼的购物区,但也曾到访过谷口度假村(Kokko Resort)和亚太员工宿舍(Yatai Staff Housing)之间的一个路口。在到达水沟谷之前,该设备于6月16日在内比都的南乌寺(Nan Oo Pagoda)被发现。

设备 B

  • 3月16日至3月28日,B设备位于水沟谷(Shwe Kokko)郊外一处空地上的不明建筑内。此前,它曾于2月26日造访过缅甸外交部。同年11月至12月期间,B设备多次造访内比都的重要地点。11月15日和12月3日,该设备被确认位于已知的部长官邸内。11月15日,B设备还造访了内比都部委区最南端的卫生部大楼。12月10日至12月30日,B设备三次造访了部委区北部的卫生部大楼,12月29日,B设备再次在缅甸外交部被发现。

设备 C

  • 7月初,C设备在内比都的各部委办公楼内被发现,并于月底前水沟谷(Shwe Kokko)。7月2日,该装置访问了交通运输部,并于7月3日以及7月9日至10日期间在各部委办公楼内被发现。7月23日,C装置出现在水沟谷(Shwe Kokko)的亚太新城(Yatai New City)内,并疑似造访了索奇督(Saw Chit Thu)的住所。该装置在2024年的大部分时间里都位于仰光市内,7月它访问了内比都和水沟谷之后,继续定期造访内比都。

设备 D

  • D设备于2024年7月22日在缅甸自然资源与环境保护部被发现。两周后,它于8月4日出现在亚太新城内。不久之后,它返回内比都,并于8月13日在能源部被发现。

设备 E

  • 2024年8月中旬,E设备造访了内比都的多个重要部委。8月12日,它造访了商务部南北两处办公楼,并于8月15日再次造访了商务部。8月14日,它访问了内比都农村公路发展部,8月15日又再次访问了该部。同一天,它还出现在民族事务部。不到一周后,E设备于8月20日出现在水沟谷(Shwe Kokko)和湄索(Mae Sot)之间的已知边境口岸,并从8月20日至8月23日多次访问了亚太新城(Yatai New City)和沟谷度假村(Kokko Resort)。

设备 F

  • 2024年5月和7月,F设备多次出现在内比都。5月21日,该设备在缅甸中央银行被发现,7月9日,该设备在交通运输部、体育与青年事务部和商务部被发现。7月29日,该设备进入卫生部的两个办公楼,7月30日,该设备再次进入体育与青年事务部。9天后,即8月8日,该设备在亚太新城内被发现。

image

参考文献

  1. https://c4ads.org/commentary/hot-lines/
  2. https://www.irrawaddy.com/opinion/analysis/the-hidden-fallout-from-chinas-cross-border-crime-crackdown-in-myanmar.html
  3. https://www.frontiermyanmar.net/en/the-mystery-man-behind-the-shwe-kokko-project/
  4. https://www.nperf.com/en/map/MM/1310460.Martaban/137098.Mytel/signal?ll=17.11979250078707&lg=97.70864144562599&zoom=9
  5. https://www.voanews.com/a/in-myanmar-internet-restrictions-and-surveillance-increase/7733716.html

2025年某交通国企内部网络安全比武 部分WriteUp

想喝🍋芭乐气泡果汁了捏 🍹~( ̄▽ ̄)

CRYPTO

part1:很明显的SM4算法

import binascii
from gmssl import sm4

def sm4_decode(key, data):
    sm4Alg = sm4.CryptSM4()  # Initialize SM4
    sm4Alg.set_key(key.encode(), sm4.SM4_DECRYPT)  # Set decryption key

    # Decrypt (ECB mode, no padding)
    ciphertext = binascii.unhexlify(data)  # Hex → bytes
    plaintext = sm4Alg.crypt_ecb(ciphertext)  # Decrypt

    # Return hex string
    return plaintext.hex()

def test():
    key = 'E1A90FB64DDE12AE'
    enHexRes = "06d7e65a973111b8a64c72150a27f61e"
    decrypted = sm4_decode(key, enHexRes)
    print("Decrypted (hex):", decrypted)

test()

然后解密hex即可得到第一部分

part2:明文 M​ 的构造方式泄露了私钥 p​ 的信息

from Crypto.Util.number import *
import gmpy2

c = int('1bd2a47a5d275ba6356e1e2bd10d6c870693be540e9318c746e807a7672f3a75cc63841170126d7dba52d7f6f9cf0f8dce9705fc1785cc670b2658b05d4b24d8918f95594844bfa920c8ffe73160c2c313b3fdbc4541ec19828165e34afa7d05271cc6fd59d08138b88c11677e6ac3b39cff525dcb19694b0388d895f53805a5e5bd8cfb947080e4855aaf83ebd85a397526f7d76d26031386900cb44a2e4bd121412bcee7a6c1e9af411e234f130e68a428596265d3ec647e50f65cb81393f4bd38389a2b9010fd715582506b9054dc235aced50757462b77a5606f116853af0c1ea3c7cf0d304f885d86081f8bac8b67b0625122f75448c5b6eb8f1cc8a0df', 16)
n = int('c2b17c86a8950f6dafe0a633890e4271cfb20c5ffda2d6b3d035afa655ed05ec16c67b18832ed887f2cea83056af079cc75c2ce43c90cce3ed02c2e07d256f240344f1734adeee6dc2b3b4bbf6dcfc68518d0a74e3e66f1865db95ef4204457e6471903c2321ac97f3b8e3d8d935896e9fc9145a30a3e24e7c320490a9944c1e94d301c8388445532699e6189f4aa6a86f67f1d9b8fb0de4225e005bd27594cd33e36622b2cd8eb2781f0c24d33267d9f29309158942b681aab81f39d1b4a73bd17431b46a89a0e4c2c58b1e24e850355c63b72392600d3fff7a16f6ef80ea515709da3ef1d28782882b0dd2f76bf609590db31979c5d1fd03f75d9d8f1c5069', 16)
e = int('10001', 16)

p = gmpy2.gcd(c, n)
q = n // p

phi = (p - 1) * (q - 1)
d = pow(e, -1, phi)

M = pow(c, d, n)

k = 2022 * 1011
m = M // (k * p)

print("Recovered m:", m)
print("Flag:", long_to_bytes(m).decode())

解密得到part2

WEB

攻击分析-1

打开日志很明显是目录扫描日志:

asynccode

攻击分析-2

asynccode

发现shell:img_5780.php

asynccode

往前翻阅日志,搜索img_5780.php

发现前一个POST为index.php

asynccode

flag{/upload/index.php&/upload/images/img_5780.php}

攻击分析-3

继续翻日志:

asynccode

asynccode

FORENSICS

WEBSHELL

冰蝎4.0流量,密钥可以搜索到04dac8afe0ca5015

asynccode

asynccode

asynccode

asynccode

Mem

使用lovelymem打开

asynccode

打开net.csv 查看相关net情况 发现存在异常端口

asynccode

即为10.112.77.140 8899

Ntlm

给出pass.txt 使用hashcat进行爆破 使用pass.txt为字典

hashcat -m 1000 "b31c6aa5660d6e87ee046b1bb5d0ff79" pass.txt

asynccode

PPC

数据泄露

提供的数据文件说明

  • 网站内存储文件:公民信息(user.csv)
  姓名,  住宅电话,       身份证,       年龄,   家庭住址,            性别
杨兰英, 15797298182 ,520330194910209167,75,贵州省遵义市习水县农贸巷999号,女
  • 说明:以上是一个公民信息(user.csv)中的内容格式,其中包含姓名、住宅电话、身份证、年龄、家庭住址、性别等。
  • 辅助信息资源
  • 省市对照表(省市对照.xlsx) :包含各省及其对应的下属城市信息,可用于识别或还原可能涉及的地理区域。
  • 身份证地区编号对照表(地区编号对照.csv) :包含身份证前6位与地区对应关系,用于还原公民身份中涉及的地区信息。

身份证规则说明

身份证号(idcard)

身份证号的⻓度为 18 位,分别是六位数字地址码、八位数字出生日期码、三位数字顺序码和最后一位数字校验码。

前1-6位:地址码

  • 第1-2位:省(自治区、直辖市)代码
  • 第3-4位:地级市(盟、自治州)代码
  • 第5-6位:县(市、区、旗)代码
  • 例如,地址码“110101”表示北京市东城区。

第7-14位:出生日期码

  • 采用“YYYYMMDD”格式,分别表示出生的年份、月份和日期。
  • 例如,“19900101”表示1990年1月1日出生,年龄计算以 2024年11月30日为基准,超过该日期也截止计算。
  • 其年龄计算规则如下:

    例:520330194910209167为1949年10月20日出生。

    1949年10月20日到2024年10月20日是75年,已度过生日,所以年龄为75岁。

    例:110101199312214859为1993年12月21日出生。

    1993年12月21日到2024年12月21日是31年,年龄计算基准以2024年11月30日截止计算,未度过生日,所以年龄为30岁。

第15-17位:顺序码

  • 在同一地址码区域内,同年同月同日出生的人区分顺序的编号。
  • 第17位:性别标识码,奇数表示男性,偶数表示女性。
  • 例如:顺序码“001”表示该区域内第1个出生者,且为男性。

第18位:校验码

  1. 将身份证号码前17位数字分别乘以不同的系数。从第一位到第十七位的系数分别是: 7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2。
  2. 将这 17 位数字和系数相乘的结果相加。
  3. 用加出来的和除以11,得到余数。
  4. 余数对应规则:
  5. 例如:身份证前17位为11010119931221485​,系数相乘的结果相加为:

1*7+1*9+0*10+1*5+0*8+1*4+1*2+9*1+9*6+3*3+1*7+2*9+2*10+1*5+4*8+8*4+5*2=223,223mod11=3​,根据(04)中的对照规则,其最后一位应为 9。

作答要求:

请根据给定的公民信息文件结合辅助信息资源校验身份证信息,匹配出正确的身份证号,并按照身份证号中的出生年月日进行排序(按照年龄从大到小进行排序)。(提交格式:flag{身份证1_身份证2_身份证3}​,举例:flag{110101198012078336_110101199312214859_110101200703169552}​)

正确示例:

蔡桂花,18767876787,110101199312214859,30,北京市东城区大马路123号,男
  • 说明:身份证地址为110101开头,即北京市东城区,符合身份证家庭住址地区(北京市东城区),此人为1993年12月21日出生,未度过生日,今年30岁,并且身份证性别为男和给定的公民信息文件对应

错误示例:

蔡桂花,18767876787,110101198011078326,56,四川省德阳市旌阳区大马路123号,男
  • 说明:身份证地址为110101开头,即北京市东城区,不符合身份证家庭住址地区(四川省德阳市旌阳区),此人为1980年11月7日出生,已度过生日,今年44岁,并且身份证性别为女和给定的公民信息文件对应不上,校验码也错误
import pandas as pd
import re
from datetime import datetime

# 加载数据
user_df = pd.read_csv('user.csv')
region_df = pd.read_csv('地区编号对照.csv', header=None, names=['地址编号', '地址'])
province_city_df = pd.read_excel('省市对照.xlsx')

# 预处理地区编号数据
region_df[['省', '市', '县']] = region_df['地址'].str.extract(r'(.+省)(.+市)(.+)', expand=True)
region_df['省'] = region_df['省'].str.replace('省', '')
region_df['市'] = region_df['市'].str.replace('市', '')

# 身份证校验系数
WEIGHTS = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
CHECK_CODES = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']

# 基准日期
REF_DATE = datetime(2024, 11, 30)

def validate_idcard(row):
    try:
        # 提取信息
        idcard = str(row['身份证']).strip()
        age = row['年龄']
        address = row['家庭住址']
        gender = row['性别']

        # 基本格式检查
        if len(idcard) != 18 or not idcard[:17].isdigit():
            return False

        # 1. 地址码验证
        region_code = idcard[:6]
        region_info = region_df[region_df['地址编号'] == region_code]
        if region_info.empty:
            return False

        # 检查地址是否匹配
        province = region_info.iloc[0]['省']
        city = region_info.iloc[0]['市']

        if province not in address or city not in address:
            return False

        # 2. 出生日期验证
        birth_date_str = idcard[6:14]
        try:
            birth_date = datetime.strptime(birth_date_str, '%Y%m%d')
        except:
            return False

        # 计算年龄
        age_diff = REF_DATE.year - birth_date.year
        if (REF_DATE.month, REF_DATE.day) < (birth_date.month, birth_date.day):
            age_diff -= 1

        if age_diff != age:
            return False

        # 3. 性别验证
        gender_code = int(idcard[16])
        if (gender == '男' and gender_code % 2 == 0) or (gender == '女' and gender_code % 2 == 1):
            return False

        # 4. 校验码验证
        total = sum(int(a) * b for a, b in zip(idcard[:17], WEIGHTS))
        check_code = CHECK_CODES[total % 11]
        if idcard[17].upper() != check_code:
            return False

        return True
    except Exception as e:
        print(f"验证过程中出错: {e}")
        return False

# 筛选有效身份证
valid_ids = user_df[user_df.apply(validate_idcard, axis=1)]['身份证'].tolist()

# 按出生日期排序
def get_birth_date(idcard):
    return idcard[6:14]

valid_ids_sorted = sorted(valid_ids, key=get_birth_date)

# 格式化输出
result = '_'.join(valid_ids_sorted)
print(f'flag{{{result}}}')

PENTEST

APK

asynccode

ezphp

PHP特性

asynccode

OSINT

纯理论

2025能源网络安全大赛 | 发⚡组 Misc 部分writeup

为❤发⚡

alarm_clock

给了vmdk,取证一下恢复一个wav和一个压缩包

image

image

很明显是SSTV,

7b01c5563befbcf1f7f3248865339e4

解压后发现是

image

按照所给hint,按照时钟进行画图:

import matplotlib.pyplot as plt
import numpy as np

direction_map = {
    0: (0, 1),   
    1: (0.5, 0.5),  
    2: (1, 0.25),  
    3: (1, 0),  
    4: (0.5, -0.5),  
    5: (0.25, -1),   
    6: (0, -1),  
    7: (-0.5, -0.5), 
    8: (-1, -0.25),  
    9: (-1, 0),  
    10: (-0.5, 0.5), 
    11: (-0.25, 1)   
}

paths = [
    [3,3,3,3,9,9,6,6,6,0,0,0,0,1,1,5,5],
    ......
]

fig, ax = plt.subplots(figsize=(12, 8))
colors = plt.cm.tab10(np.linspace(0, 1, len(paths)))

for i, path in enumerate(paths):
    x, y = [0], [0]
    for d in path:
        dx, dy = direction_map[d]
        x.append(x[-1] + dx)
        y.append(y[-1] + dy)
    x = np.array(x) + i * 5
    y = np.array(y)
    ax.plot(x, y, color=colors[i], linewidth=2, label=f'Path {i+1}')

ax.set_aspect('equal')
ax.axis('off')
plt.title("Clock Direction Paths (Simplified)", fontsize=14)
plt.legend(loc='upper right', fontsize=8)
plt.tight_layout()
plt.show()

image

Bluetooth

观察流量包,发现是考L2CAP层协议解析,

image

提取一下Bluetooth L2CAP Payload

tshark -r Bluetooth.pcapng  -e "btl2cap.payload" -T fields > result.txt

image

发现result中长度34位里的数据只有后三位不一样,提取出来


def extract_third_last(filename):
    with open(filename, 'r', encoding='utf-8') as f:
        lines = f.readlines()

    result = []

    for line in lines:
        line = line.strip()
        if len(line) == 36:
            result.append(line[-3])

    return result

if __name__ == "__main__":
    filename = 'result.txt'
    chars = extract_third_last(filename)
    for ch in chars:
        print(ch)

image

发现只有 01248,0作为分隔符号,所以我们需要将0​批量替换为空然后利用正则:1 1 1​与1 1​是1,2 2 2​与 2 2​是2,4 4 4​与4 4​ 是4 ,8 8 8​与8 8​是8

import re

text = """
2 2 2    4 4 4    2 2 2    4 4 4
"""

result = re.sub(r'(\d)(?:\s\1){1,2}', r'\1', text)

print(result.strip())

转变为4进制,1替换成0,2替换成1,4替换成2,8替换成3

121212301201121313230......

按两位一组组合为四进制数,转换为十进制字符:

text = "121212301201121313230......"

# 每两个字符一组
pairs = [text[i:i+2] for i in range(0, len(text), 2)]

# 将每组视为4进制并转为10进制
decimal_values = [int(pair, 4) for pair in pairs]

print(decimal_values)
# [6, 6, 6, 12, 6, 1, 6, 7, 7, 11, ......]
def convert_numbers_to_custom_encoding(numbers):
    result = []
    for num in numbers:
        if 0 <= num <= 9:
            result.append(str(num))
        elif 10 <= num <= 15:
            result.append(chr(num - 10 + ord('A')))
        else:
            result.append('?')  # 这里用 '?' 表示无效数字
    return ''.join(result)

numbers = [6, 6, 6, 12, 6, 1, 6, 7, 7, 11, ......]

encoded_str = convert_numbers_to_custom_encoding(numbers)
print(encoded_str)
# 666C61677B......

image

Smuggling arbitrary data through an emoji | 通过emoji走私任意数据

https://paulbutler.org/2025/smuggling-arbitrary-data-through-an-emoji/

写了个python版本,感觉有人是会拿来比赛出题的。

Unicode 码点

Unicode 是计算机科学领域的一项业界标准,包括字符集和编码方案。它为每种语言中的每个字符设定了统一且唯一的二进制编码,通常用两个字节表示一个字符。Unicode 码点(Code Point)是指 Unicode 字符在 Unicode 字符集中的唯一编号。

Unicode 编码格式

Unicode 编码格式有多种,其中最常见的是 UTF-8UTF-16。UTF-8 是一种可变长度的编码方式,根据字符的不同范围使用不同长度的编码。例如:

  • 000000-00007F: 0xxxxxxx
  • 000080-0007FF: 110xxxxx 10xxxxxx
  • 000800-00FFFF: 1110xxxx 10xxxxxx 10xxxxxx
  • 010000-10FFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

Unicode 定义了 256 个代码点作为“变体选择器”,从 VS-1 到 VS-256。这些变体选择器本身没有可见的显示效果,但用于修改前一个字符的显示方式。例如,代码点 U+0067​(字符g​)后跟 U+FE01​(VS-2)仍然显示为小写g​,与单独的g​相同。但如果复制并粘贴该字符,变体选择器也会随之携带。

由于 256 足以表示一个字节,这为我们提供了一种在任何其他 unicode 代码点中“隐藏”一个字节数据的方法。

变体选择器

按照Paul Butler的思路,假设要编码字符串 "hello",其 ASCII 码为 [0x68, 0x65, 0x6c, 0x6c, 0x6f]​。可以将每个字节映射到一个变体选择器,然后将这些变体选择器附加到一个基字符(如空格或emoji)后面。例如,使用emoji符作为基字符,编码后的字符串可能看起来像一个普通的表情符号,但实际上包含了隐藏的数据。

变体选择器的代码点被分为两段:最初的 16 个在 U+FE00​ 到 U+FE0F​ 之间,其余的 240 个在 U+E0100​ 到 U+E01EF​ 之间。

要从字节转换为变体选择器,我们可以执行类似以下 Rust 代码的操作:

fn byte_to_variation_selector(byte: u8) -> char {
    if byte < 16 {
        char::from_u32(0xFE00 + byte as u32).unwrap()
    } else {
        char::from_u32(0xE0100 + (byte - 16) as u32).unwrap()
    }
}

然后,要编码一系列字节,我们可以在一个基础字符后面连接多个这样的变体选择器:

fn encode(base: char, bytes: &[u8]) -> String {
    let mut result = String::new();
    result.push(base);
    for byte in bytes {
        result.push(byte_to_variation_selector(*byte));
    }
    result
}

为了编码字节 [0x68, 0x65, 0x6c, 0x6c, 0x6f]​,我们可以运行以下代码:

fn main() {
    println!("{}", encode('😊', &[0x68, 0x65, 0x6c, 0x6c, 0x6f]));
}

输出就是:

😊󠅘󠅕󠅜󠅜󠅟

解码

fn variation_selector_to_byte(variation_selector: char) -> Option<u8> {
    let variation_selector = variation_selector as u32;
    if (0xFE00..=0xFE0F).contains(&variation_selector) {
        Some((variation_selector - 0xFE00) as u8)
    } else if (0xE0100..=0xE01EF).contains(&variation_selector) {
        Some((variation_selector - 0xE0100 + 16) as u8)
    } else {
        None
    }
}

fn decode(variation_selectors: &str) -> Vec<u8> {
    let mut result = Vec::new();

    for variation_selector in variation_selectors.chars() {
        if let Some(byte) = variation_selector_to_byte(variation_selector) {
            result.push(byte);
        } else if !result.is_empty() {
            return result;
        }
        // note: we ignore non-variation selectors until we have
        // encountered the first one, as a way of skipping the "base
        // character".
    }

    result
}

使用示例如下:

use std::str::from_utf8;

fn main() {
    let result = encode('😊', &[0x68, 0x65, 0x6c, 0x6c, 0x6f]);
    println!("{:?}", from_utf8(&decode(&result)).unwrap()); // "hello"
}

基字符(如空格或表情符号)不需要一定是emoji符号,任何 Unicode 字符都可以作为基字符。

image

python示例

encode

将字节(0-255​)转换为对应的变体选择器字符,判断字节大小并选择对应的变体选择器范围。将基字符和字节数组进行组合,依次生成编码后的字符串。

def byte_to_variation_selector(byte: int) -> str:
    """Converts a byte to a variation selector character."""
    if byte < 16:
        return chr(0xFE00 + byte)
    else:
        return chr(0xE0100 + (byte - 16))

def encode(base: str, bytes: list) -> str:
    """Encodes a base character with a list of bytes as variation selectors."""
    result = [base]
    for byte in bytes:
        result.append(byte_to_variation_selector(byte))
    return ''.join(result)

if __name__ == "__main__":
    base = ' '
    byte_sequence = [0x41, 0x6e, 0x64, 0x79, 0x4e, 0x6f, 0x65, 0x6c]
    encoded_str = encode(base, byte_sequence)
    print(encoded_str)

decode

解密思路就是将每个变体选择器字符映射回其对应的字节值,然后,编写一个函数,遍历输入字符串,提取所有有效的变体选择器字符,并将其转换为字节值。

def variation_selector_to_byte(variation_selector: str) -> int:
    code_point = ord(variation_selector)
    if 0xFE00 <= code_point <= 0xFE0F:
        return code_point - 0xFE00
    elif 0xE0100 <= code_point <= 0xE01EF:
        return code_point - 0xE0100 + 16
    else:
        raise ValueError(f"无效的变体选择器字符:{variation_selector}")
def decode(variation_selectors: str) -> bytes:
    result = bytearray()
    for char in variation_selectors:
        try:
            byte = variation_selector_to_byte(char)
            result.append(byte)
        except ValueError:
            if result:
                break
    return bytes(result)
encoded_str = ' 󠄱󠅞󠅔󠅩󠄾󠅟󠅕󠅜'
decoded_bytes = decode(encoded_str)
decoded_str = decoded_bytes.decode('utf-8')
print(decoded_str) 

Annual Summary of 2024 | To be Better.

2024年12月24日22:00 | 平安夜🎄,这就到年底了,每天的日程还是挺满的,所以自己大概率是没办法抽出很多时间去一次性完成年终总结,于是打算提前几天动手,利用每晚的休息时间写一点,积少成多嘛。

前言

2024对我来说注定是不平凡的一年,一篇长达四年的大学青春小说在我的笔下迎来了属于它的结局。这篇小说虽然没有波澜壮阔的开场,但是有惊喜,也有遗憾,我自认为自己是一个念旧甚至到有点执着的人,每每翻过它时都不禁一叹:此去经年......大半个中国的游历;四年严苛的警务化管理;紧张的公安联考;一场轰轰烈烈却缘分未到的恋爱;感慨万千的毕业典礼;荣幸受邀参与了几场省部级、国家级安全比赛以及部门比武的出题、赛事支持工作;以及一场关于人生的豪赌。

做了什么?

b73037a5f259a395cf20b3f8528a65c

今年无疑是高产的一年,加上外出参赛、旅游、出差,轨迹地图又有了新成员,向南最远来到了福建福州,向西来到了陕西西安,而向北最远是内蒙古呼和浩特,除此之外,北京、天津、杭州、上海、南京、济南、青岛......见识到了不一样的风景

88a97050015b0cb7a0776c942b3f26d5d81a6c61c4e1b1d03d24369a6ab6a2

3b852a4a94987f2b313473628372d10e664954718df134ed4bd939f52f4fe1

46f9a5610e41f16bb4621e9cf6ac794ea9a66c300b7110113e634a0a97fbbc

还有许多祖国的大好河山还没有去探索,尤其是西部地区更是引人神往,所以后期看看有没有机会,弥补这方面的空白。

今年技术文章产量不高,写了20篇,其中在博客上更新了15篇,前期以分享比赛WriteUP为主,中间穿插研究了一些小玩意,比如网易云音乐前端加密算法的分析、手指指纹识别的分析,后期以学习如何分析国外高级持续性威胁组织的样本并详细记录为主,如APT-K-47 Asyncshell Version3 AnalysisAPT-K-47 Asyncshell Version1 AnalysisThe Analysis of l0ader_shell and Glutton’s client_task | 黑吃黑👍等。

在此,感谢网络安全战队Chamd5 & Mini-VenomCTFIOT平台微步在线社区微步在云沙箱平台奇安信X实验室​、VirusTotal等各大网络安全组织的技术分享与支持,还有为了网络安全事业默默不停奉献的各位,正因为有大家的坚守,这个世界才逐渐变得更加安全与美好。

之前很多师傅好奇我的共同富裕板块进展咋样了?OK,现在我们揭秘一下。感谢各位老板的支持与抬爱,帮助师傅们累计达成合作意向20余次,比较成功。关于收费问题,请大家放心,过去是公益发布,现在以及将来也不会改变。

会有遗憾吗?

6b6369b7a6af00ee1fdf9f31dfc60d6

我持留白态度,硬要讲的话,我只说一句:祝天下有情人终成眷属,即使两人面临暂时的异地也不要害怕,双鸟暂时离分,必有重逢之日。如果真的最终没走到一起,却你们彼此相互努力过,那就没什么值得遗憾的。

01913f501b1a6b0b9c6d4082a4d8699

人生,不过就是一场豪赌。

生活是写好的剧本吗?就像活在一部电影里那样。

2023年11月1日,我记得特别清楚,奋斗了整整一天的蓝帽杯终于落下帷幕(真·黑灯搏杀,绷不住了),在返回学校后也是正式收心,开始了公安联考的学习。很多人问我,我花了大部分时间在网安学习和比赛上,那留给联考准备的时间够吗?我如实告诉大家:确实是非常紧张,每天都会有点焦虑,尤其是在看到周围同学得心应手的样子更是担心自己,先别说拔高了,能不能正常看完基础课都会是问题。但是没办法,自己做的孽就要自己承担。在很早之前我在实习日记里写过这样一句话:“我也想同情你,但我实在是做不到。人总要为自己的行为付出相应的代价。”一年前的子弹正中了我的眉心。那就啥也别说了,玩命看吧,每天都在两点左右回宿舍,有的时候太晚就直接在机房趴在椅子上睡着了。也算是功夫不负有心人,用最后一个月的时间里突击完了要学的基础内容。但是考试大家都懂,如果说学的是1+1=2,考的就是黎曼猜想(?),到底能考咋样对我来说就是运气问题了。

2024年1月,联考终于结束了。现在来看,我的运气还不错,综合来看考的还算理想,在大家成绩里也能算中上游水平,我甚是满意,尤其是申论考了68分更是给了我一个惊喜,我不奢求别的,毕竟蝴蝶飞不过沧海,谁又忍心责怪呢?突击要是能与别人日以继夜的勤勤恳恳相比肩,那就是对别人的不尊重了。

2024年6月,如期选岗,选得好不错,是个好岗位。但没过几天,我迎来了第二此机会,但与其说是机会,倒不如说是赌博,这次要押上的是自己的人生,它远没有联考选岗带来的真实,更像是镜中花、水中月。一边是联考的岗位,另一边是放弃这个现有的铁饭碗去选择一个还没有定局的考试,我觉得有100个人面临同样选择时,还是会选择联考的岗位,人生大事,可马虎不得;但我特立独行惯了,在纠结良久之后,也听遍了家里长辈的劝告之言,还是做出了放弃的决定。

image

声明发过去之后,感觉自己如释重负,甚至是有点飘飘然,有点小帅。

这次,幸运女神再次展现了她的微笑🙂

中间虽几经波折,此处我就一笔带过,总之自己是如愿来到了青岛,并且把自己的爱好变成了职业,不得不说,这是一件幸福的事。

回到上面,生活是写好的剧本吗?最起码在我看来不是的,希望大家亦是如此。

c03ca12fa4162eff2e6376b74b53f26

新的一年

不论是否相识,2025,祝看到这儿的你,天天开心,希望大家都能去奋力追求自己所爱的人和事,也希望我们都能够诚实地对待每一个当下,用每一个当下去触摸永恒,用每一个当下去做你应该做的事情,用每一个当下去爱你身边的人,用每一个当下去传递温暖,尤其在这样一个寒冷的冬天,不辜负每一场热爱与期待。

c6c0b6cfc6913d9a666b548cfe14289

今年我想用这样一句话勉励自己,也与大家共勉:我深知自己是一根廉价的火柴,本就是一棵朽木,没资格谈什么伟大与不朽,燃烧就是我存在的唯一价值(今天不燃烧过两天就返潮了,想烧也烧不着)。

嗷对,差点忘了,SanDieg0 | 圣地亚哥皮蛋-AndyNoel,断开连接......

了吗?