
最后一舞离一等奖最近的一次,因为数据安全第二题浪费太多时间,导致web2来不及了,开始因为fenjing没换模板,后面手注爆的差一点😭
还是把希望寄托给学弟了哈哈哈
Web
咋输不进去捏
题目内容:咋输不进去捏,咋这么奇怪捏?

根据前端源码就行了

Crypto
简单数学题
题目内容:简单数学题
from Crypto.Util.number import *
sum_pq = 15870713655456272818998868095126610389501417235762009793315127525027164306871912572802442396878309282140184445917718237547340279497682840149930939938364752
diff_pq = 836877201325346306269647062252443025692393860257609240213263622058769344319275021861627524327674665653956022396760961371531780934904914806513684926008590
e = 65537
c = 24161337439375469726924397660125738582989340535865292626109110404205047138648291988394300469831314677804449487707306159537988907383165388647811395995713768215918986950780552907040433887058197369446944754008620731946047814491450890197003594397567524722975778515304899628035385825818809556412246258855782770070
p = (sum_pq + diff_pq) // 2
q = (sum_pq - diff_pq) // 2
phi = (p - 1) * (q - 1)
d = pow(e, -1, phi)
n = p * q
m = pow(c, d, n)
flag = long_to_bytes(m)
print(f"Flag: {flag.decode('utf-8')}")
AES
题目内容:AES
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import hashlib
iv_str = "0123456789abcdef"
ciphertext_b64 = "H4vkfGfsU+qBEwaa7ea9gBkRcraMqbe4BGaxDb/9JG4zGleqT1VxyzGbDj/yuQn8"
password = "Cryptography"
def decrypt_aes_cbc(ciphertext_b64, password, iv_str):
try:
key = hashlib.md5(password.encode()).digest()[:16]
ciphertext = base64.b64decode(ciphertext_b64)
iv = iv_str.encode()
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted_padded = cipher.decrypt(ciphertext)
plaintext = unpad(decrypted_padded, AES.block_size)
return plaintext.decode('utf-8')
except Exception as e:
print(f"解密出错: {e}")
return None
plaintext_decrypted = decrypt_aes_cbc(ciphertext_b64, password, iv_str)
if plaintext_decrypted is not None:
print(f"解密后的明文: {plaintext_decrypted}")
else:
print("解密失败")
base64
题目内容:
REFTQ1RGezQwYjkwNTA4ZjYzYmM3OTYyOGIyZWRjNzc1ZTE0OGI5fQ==请尝试使用base64解码
DASCTF{40b90508f63bc79628b2edc775e148b9}
Misc
easySteg0
题目内容:easy stego
图片备注中有表

table: FI0EHKRkclAYN/xvgim2XCUdSf8O6osJVPb+LZu5nyQjqGt49BDwhrz3pWTaeM17
文件尾处找到压缩包文件

526172211a0701003392b5e50a01050600050101808000959525532e02030b970004970020197f88b9800000126561737953746567302f666c61672e7478740a030275a1a3332d4adc014441534354467b6e6f666c6167686572655f6e7466737d35856c841e032308c1800004b68000003fc2ed198003000353544d07073a632e747874c1a53e2656423f933c83ab6b96c84084e4fc49041c0944381453877fa55c87d4fbed9e7e1b2569fd7c51d15370ed146215046bfbfa21bfb135379c9b780a85ec80969d8de92302030b0005001000000000800000096561737953746567300a030244a0b7fb2c4adc011d77565103050400
解压后看见两个文件其中一个为密文

iHK2griRswoPfuKPNEluNwXpN+KuSUC+NwoPf2lPf2LBNEL9Nul+Jg

DASCTF{7afaa02f35821faec37ae2ae910902bc}
Simple_Domain
题目内容:dict and system!!!
磁盘读取工具中,kali自带的secretsdump.py可以直接读取
python3 /usr/share/doc/python3-impacket/examples/secretsdump.py -ntds ntds.dit -system system LOCA

└─# python3 /usr/share/doc/python3-impacket/examples/secretsdump.py -ntds ntds.dit -system system LOCAL
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies
[*] Target system bootKey: 0xae5564d04e225ccba0d2643161c48b10
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Searching for pekList, be patient
[*] PEK # 0 found and decrypted: ddb6a826834aad5816b4c80b5220276b
[*] Reading and decrypting hashes from ntds.dit
KINGSLANDING$:1001:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
Administrator:500:aad3b435b51404eeaad3b435b51404ee:dbd13e1c4e338284ac4e9874f7de6ef4:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
vagrant:1000:aad3b435b51404eeaad3b435b51404ee:e02bc503339d51f71d913c245d35b50b:::
WINTERFELL$:1001:aad3b435b51404eeaad3b435b51404ee:aa685d65871bfdf122009745b03f8e01:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:8bf38852ab8d3a887ae867500c9a48c5:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
vagrant:1000:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
ESSOS$:1104:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
NORTH$:1105:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
CASTELBLACK$:1104:aad3b435b51404eeaad3b435b51404ee:723026eda8195b4bd9e82caef809c40f:::
arya.stark:1109:aad3b435b51404eeaad3b435b51404ee:4f622f4cd4284a887228940e2ff4e709:::
tywin.lannister:1113:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
eddard.stark:1110:aad3b435b51404eeaad3b435b51404ee:d977b98c6c9282c5c478be1d97b237b8:::
jaime.lannister:1114:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
catelyn.stark:1111:aad3b435b51404eeaad3b435b51404ee:cba36eccfd9d949c73bc73715364aff5:::
robb.stark:1112:aad3b435b51404eeaad3b435b51404ee:831486ac7f26860c9e2f51ac91e1a07a:::
cersei.lannister:1115:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
tyron.lannister:1116:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
sansa.stark:1113:aad3b435b51404eeaad3b435b51404ee:2c643546d00054420505a2bf86d77c47:::
brandon.stark:1114:aad3b435b51404eeaad3b435b51404ee:84bbaa1c58b7f69d2192560a3f932129:::
robert.baratheon:1117:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
joffrey.baratheon:1118:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
rickon.stark:1115:aad3b435b51404eeaad3b435b51404ee:7978dc8a66d8e480d9a86041f8409560:::
hodor:1116:aad3b435b51404eeaad3b435b51404ee:337d2667505c203904bd899c6c95525e:::
renly.baratheon:1119:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
stannis.baratheon:1120:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
jon.snow:1117:aad3b435b51404eeaad3b435b51404ee:b8d76e56e9dac90539aff05e3ccb1755:::
samwell.tarly:1118:aad3b435b51404eeaad3b435b51404ee:f5db9e027ef824d029262068ac826843:::
petyer.baelish:1121:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
lord.varys:1122:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
jeor.mormont:1119:aad3b435b51404eeaad3b435b51404ee:6dccf1c567c56a40e56691a723a49664:::
sql_svc:1120:aad3b435b51404eeaad3b435b51404ee:84a5092f53390ea48d660be52b93b804:::
maester.pycelle:1123:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
SEVENKINGDOMS$:1121:aad3b435b51404eeaad3b435b51404ee:1b89cf55c349b296a8fc34f95d7580e0:::
[*] Kerberos keys from ntds.dit
Administrator:aes256-cts-hmac-sha1-96:e7aa0f8a649aa96fab5ed9e65438392bfc549cb2695ac4237e97996823619972
Administrator:aes128-cts-hmac-sha1-96:bb7b6aed58a7a395e0e674ac76c28aa0
Administrator:des-cbc-md5:fe58cdcd13a43243
vagrant:aes256-cts-hmac-sha1-96:aa97635c942315178db04791ffa240411c36963b5a5e775e785c6bd21dd11c24
vagrant:aes128-cts-hmac-sha1-96:0d7c6160ffb016857b9af96c44110ab1
vagrant:des-cbc-md5:16dc9e8ad3dfc47f
WINTERFELL$:aes256-cts-hmac-sha1-96:c0880c4af7d14d09402a8138bb48d1b526e1fa5f5fc4ce4f9fe89ef2422eb304
WINTERFELL$:aes128-cts-hmac-sha1-96:23b19c152d6b8c3aa275b16b082675ed
WINTERFELL$:des-cbc-md5:7ff72c75d5d683b5
krbtgt:aes256-cts-hmac-sha1-96:82b8cbbbe398df35611657a4fab06f32fedc6a9c0036ae6e0988193de5c30a8c
krbtgt:aes128-cts-hmac-sha1-96:d4a753716a2747b19c1eb09a9e0d4a97
krbtgt:des-cbc-md5:708ad92523fdf7b6
CASTELBLACK$:aes256-cts-hmac-sha1-96:ac20a1c7051889152b6811094c6e52bd854d347a0e9b52ad63b6ea98794b1423
CASTELBLACK$:aes128-cts-hmac-sha1-96:c1fe9a27470b9bd8e0e9537e4f63b3ae
CASTELBLACK$:des-cbc-md5:fec498bf3eea5ef8
arya.stark:aes256-cts-hmac-sha1-96:2001e8fb3da02f3be6945b4cce16e6abdd304974615d6feca7d135d4009d4f7d
arya.stark:aes128-cts-hmac-sha1-96:8477cba28e7d7cfe5338d172a23d74df
arya.stark:des-cbc-md5:13525243d6643285
eddard.stark:aes256-cts-hmac-sha1-96:f6b4d01107eb34c0ecb5f07d804fa9959dce6643f8e4688df17623b847ec7fc4
eddard.stark:aes128-cts-hmac-sha1-96:5f9b06a24b90862367ec221a11f92203
eddard.stark:des-cbc-md5:8067f7abecc7d346
catelyn.stark:aes256-cts-hmac-sha1-96:c8302e270b04252251de40b2bd5fba37395b55d5ed9ac95e03213dc739827283
catelyn.stark:aes128-cts-hmac-sha1-96:50ce7e2ad069fa40fb2bc7f5f9643d93
catelyn.stark:des-cbc-md5:6b314670a2f84cfb
robb.stark:aes256-cts-hmac-sha1-96:d7df5069178bbc93fdc34bbbcb8e374fd75c44d6ce51000f24688925cc4d9c2a
robb.stark:aes128-cts-hmac-sha1-96:b2965905e68356d63fedd9904357cc42
robb.stark:des-cbc-md5:c4b62c797f5dd01f
sansa.stark:aes256-cts-hmac-sha1-96:cd2460a78e8993442498d3f242a88ae110ec6556e40c8add6aab12cfb44b3fa1
sansa.stark:aes128-cts-hmac-sha1-96:18b9d10bd18d1956ba73c14426ec519f
sansa.stark:des-cbc-md5:e66445757c31c176
brandon.stark:aes256-cts-hmac-sha1-96:6dd181186b68898376d3236662f8aeb8fa68e4b5880744034d293d18b6753b10
brandon.stark:aes128-cts-hmac-sha1-96:9de3581a163bd056073b71ab23142d73
brandon.stark:des-cbc-md5:76e61fda8a4f5245
rickon.stark:aes256-cts-hmac-sha1-96:79ffda34e5b23584b3bd67c887629815bb9ab8a1952ae9fda15511996587dcda
rickon.stark:aes128-cts-hmac-sha1-96:d4a0669b1eff6caa42f2632ebca8cd8d
rickon.stark:des-cbc-md5:b9ec3b8f2fd9d98a
hodor:aes256-cts-hmac-sha1-96:a33579ec769f3d6477a98e72102a7f8964f09a745c1191a705d8e1c3ab6e4287
hodor:aes128-cts-hmac-sha1-96:929126dcca8c698230b5787e8f5a5b60
hodor:des-cbc-md5:d5764373f2545dfd
jon.snow:aes256-cts-hmac-sha1-96:5a1bc13364e758131f87a1f37d2f1b1fa8aa7a4be10e3fe5a69e80a5c4c408fb
jon.snow:aes128-cts-hmac-sha1-96:d8bc99ccfebe2d6e97d15f147aa50e8b
jon.snow:des-cbc-md5:084358ceb3290d7c
samwell.tarly:aes256-cts-hmac-sha1-96:b66738c4d2391b0602871d0a5cd1f9add8ff6b91dcbb7bc325dc76986496c605
samwell.tarly:aes128-cts-hmac-sha1-96:3943b4ac630b0294d5a4e8b940101fae
samwell.tarly:des-cbc-md5:5efed0e0a45dd951
jeor.mormont:aes256-cts-hmac-sha1-96:be10f893afa35457fcf61ecc40dc032399b7aee77c87bb71dd2fe91411d2bd50
jeor.mormont:aes128-cts-hmac-sha1-96:1b0a98958e19d6092c8e8dc1d25c788b
jeor.mormont:des-cbc-md5:1a68641a3e9bb6ea
sql_svc:aes256-cts-hmac-sha1-96:24d57467625d5510d6acfddf776264db60a40c934fcf518eacd7916936b1d6af
sql_svc:aes128-cts-hmac-sha1-96:01290f5b76c04e39fb2cb58330a22029
sql_svc:des-cbc-md5:8645d5cd402f16c7
SEVENKINGDOMS$:aes256-cts-hmac-sha1-96:c2ac7ab055d49ba523564eab3bfe041e026ce6745413cb8ea19514771de06080
SEVENKINGDOMS$:aes128-cts-hmac-sha1-96:5796cbf539ac141f8fed3a05892eff12
SEVENKINGDOMS$:des-cbc-md5:92d5bf79fe57158a
[*] Cleaning up... 根据压缩包注释提示密码长32且与Administrator有关经过搜索尝试最后解压码为dbd13e1c4e338284ac4e9874f7de6ef4

DASCTF{dbd13e1c4e338284ac4e9874f7de6ef9}
AI
寻找可爱的小狗
直接翻6只猫出来

import hashlib
# 需要加密的字符串
text = "26c39cf8-55fb-4899-82bc-442cf4627d95.jpg+6e17fffa-b696-4769-9b43-e0f453f8098d.jpg+7a19da17-9f4a-411b-bac7-83d2454d868a.jpg+897a3a87-dfcf-4233-8097-6bba2e6507ba.jpg+c6b1099a-d626-4cbd-94fc-32aa46ffb02b.jpg+d5117480-7943-48f8-9e79-67fdd51092d2.jpg"
# 计算 MD5 哈希值
md5_hash = hashlib.md5(text.encode('utf-8')).hexdigest()
# 输出结果
print(f'[+] str :{text}')
print(f'[+] MD5 hash :{md5_hash}')
# [+] MD5 hash :4c5e686c28a5409e6f19598b97d39964DS
check1
题目内容:某互联网公司在数据迁移过程中发现用户注册信息存在不一致,不规范的问题,需要对用户数据进行规范性和一致性验证,确保数据质量符合业务要求,将提取出的正确的数据保存为csv文件,提交到验证靶机,若准确率通过则给出flag。
import re
from datetime import datetime
def validate_id_card(id_card):
"""验证身份证号格式和校验码"""
# 长度验证
if len(id_card) != 18:
return False
# 字符验证:前17位为数字,第18位为数字或X
if not re.match(r'^\d{17}[\dXx]$', id_card):
return False
# 校验码验证
# 加权因子
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']
# 计算前17位数字的加权和
sum_value = sum(int(id_card[i]) * weights[i] for i in range(17))
# 计算校验码
check_code = check_codes[sum_value % 11]
return id_card[17].upper() == check_code
def get_gender_from_id_card(id_card):
"""从身份证号获取性别"""
# 第17位(倒数第2位)奇数为男性,偶数为女性
gender_digit = int(id_card[16])
return '男' if gender_digit % 2 == 1 else '女'
def validate_phone(phone):
"""验证手机号格式"""
# 长度为11位数字,开头为1
return re.match(r'^1\d{10}$', phone) is not None
def validate_name(name):
"""验证姓名格式(2-4个汉字)"""
# 汉字的Unicode范围
return re.match(r'^[\u4e00-\u9fa5]{2,4}$', name) is not None
def validate_date_format(date_str):
"""验证日期格式是否正确"""
try:
datetime.strptime(date_str, '%Y-%m-%d')
return True
except ValueError:
return False
def validate_datetime_format(datetime_str):
"""验证时间格式是否正确"""
try:
datetime.strptime(datetime_str, '%Y-%m-%d %H:%M:%S')
return True
except ValueError:
return False
def validate_time_logic(birth_date, register_time, login_time):
"""验证时间逻辑"""
try:
birth_dt = datetime.strptime(birth_date, '%Y-%m-%d')
register_dt = datetime.strptime(register_time, '%Y-%m-%d %H:%M:%S')
login_dt = datetime.strptime(login_time, '%Y-%m-%d %H:%M:%S')
# 出生日期必须早于注册时间
if birth_dt >= register_dt:
return False, "出生日期必须早于注册时间"
# 注册时间必须早于或等于最后登录时间
if register_dt > login_dt:
return False, "注册时间必须早于或等于最后登录时间"
return True, ""
except ValueError as e:
return False, f"时间格式错误: {str(e)}"
def validate_row(data_list, original_line):
"""验证一行数据"""
if len(data_list) != 8:
return False, f"数据字段数量不正确,期望8个字段,实际{len(data_list)}个字段"
customer_id, name, id_card, gender, phone, birth_date, register_time, login_time = data_list
# 1. 身份证号验证
if not validate_id_card(id_card):
return False, "身份证号格式或校验码错误"
# 2. 性别一致性验证
id_gender = get_gender_from_id_card(id_card)
if gender != id_gender:
return False, f"性别不一致,身份证号对应性别为{id_gender},但字段值为{gender}"
# 3. 出生日期一致性验证
id_birth_date = id_card[6:14] # 身份证号第7-14位
formatted_birth_date = f"{id_birth_date[:4]}-{id_birth_date[4:6]}-{id_birth_date[6:8]}"
if birth_date != formatted_birth_date:
return False, f"出生日期不一致,身份证号对应出生日期为{formatted_birth_date},但字段值为{birth_date}"
# 4. 手机号验证
if not validate_phone(phone):
return False, "手机号格式错误"
# 5. 姓名验证
if not validate_name(name):
return False, "姓名格式错误,必须为2-4个汉字"
# 6. 时间格式验证
if not validate_date_format(birth_date):
return False, "出生日期格式错误"
if not validate_datetime_format(register_time):
return False, "注册时间格式错误"
if not validate_datetime_format(login_time):
return False, "最后登录时间格式错误"
# 7. 时间逻辑验证
time_valid, time_error = validate_time_logic(birth_date, register_time, login_time)
if not time_valid:
return False, time_error
return True, ""
def main():
input_file = 'data.txt' # 输入文件名
output_file = '2.txt' # 输出文件名
try:
with open(input_file, 'r', encoding='utf-8') as f:
lines = f.readlines()
valid_lines = []
invalid_lines = []
print("开始验证数据...")
for i, line in enumerate(lines, 1):
line = line.strip()
if not line: # 跳过空行
continue
try:
# 按逗号分割数据
data_list = [item.strip() for item in line.split(',')]
# 验证数据
is_valid, error_msg = validate_row(data_list, line)
if is_valid:
valid_lines.append(line)
else:
invalid_lines.append(f"{line}")
except Exception as e:
invalid_lines.append(f"第{i}行解析错误: {line} (错误: {str(e)})")
# 写入验证结果
with open(output_file, 'w', encoding='utf-8') as f:
if invalid_lines:
f.write("不符合要求的数据:\n")
for line in invalid_lines:
f.write(line + '\n')
else:
f.write("所有数据都符合要求\n")
# 输出统计信息
print(f"总行数: {len(lines)}")
print(f"有效行数: {len(valid_lines)}")
print(f"无效行数: {len(invalid_lines)}")
if invalid_lines:
print("\n无效数据已写入2.txt文件")
else:
print("\n所有数据都符合要求")
except FileNotFoundError:
print(f"错误: 找不到文件 {input_file}")
except Exception as e:
print(f"处理文件时发生错误: {str(e)}")
if __name__ == "__main__":
main()

Shop
题目内容:本题目要求分析电商平台的交易数据,识别存在金额异常、银行卡异常或频率异常行为的可疑用户,并将结果保存到CSV文件中并提交到验证靶机,若正确率达标则会给出flag。
当时整了好久,浪费太多时间了,最后还是一个一个分析的然后,最后整合在一块
# 金额异常
import re
from collections import defaultdict
from datetime import datetime
# 定义商品类型与对应的金额范围
price_ranges = {
'电子产品': (100, 5000),
'服装鞋包': (50, 1000),
'家居用品': (30, 2000),
'美妆护肤': (20, 800),
'食品饮料': (5, 300),
'图书文具': (5, 200),
'运动户外': (50, 3000)
}
# 存储用户的订单信息
user_orders = defaultdict(list)
# 存储异常用户
abnormal_users = set()
# 读取并处理文件
with open('data.txt', 'r', encoding='utf-8') as file:
for line_num, line in enumerate(file, 1):
line = line.strip()
if not line:
continue # 忽略空行
try:
order_info = line.split(',')
order_id, user_id, amount, timestamp, product_type, payment_method, bank_card, register_days, history_orders = order_info
# 校验字段数量是否正确
if len(order_info) != 9:
print(f"第{line_num}行字段数量不正确: {line}")
with open('1.txt', 'a', encoding='utf-8') as abnormal_file:
abnormal_file.write(f"{user_id},字段数异常\n")
continue
# 验证金额格式是否为数字
try:
amount = float(amount)
except ValueError:
print(f"第{line_num}行金额格式错误: {amount}")
with open('1.txt', 'a', encoding='utf-8') as abnormal_file:
abnormal_file.write(f"{user_id},金额格式错误\n")
continue
# 检查商品类型是否存在于规则中
if product_type not in price_ranges:
print(f"第{line_num}行商品类型未定义: {product_type}")
with open('1.txt', 'a', encoding='utf-8') as abnormal_file:
abnormal_file.write(f"{user_id},商品类型异常\n")
continue
min_price, max_price = price_ranges[product_type]
# 校验金额是否在合理范围内
if amount < min_price or amount > max_price:
print(f"第{line_num}行用户{user_id}的订单金额{amount}超出商品类型{product_type}的价格范围({min_price}到{max_price})")
abnormal_users.add(user_id)
# 将数据存入用户的订单列表
user_orders[user_id].append({
'amount': amount,
'product_type': product_type,
'min_price': min_price,
'max_price': max_price
})
except Exception as e:
print(f"处理第{line_num}行时出错: {line}")
with open('1.txt', 'a', encoding='utf-8') as abnormal_file:
abnormal_file.write(f"未知,解析错误\n")
# 检查每个用户的订单是否存在金额异常
with open('1.txt', 'a', encoding='utf-8') as abnormal_file:
for user_id, orders in user_orders.items():
for order in orders:
amount = order['amount']
min_price = order['min_price']
max_price = order['max_price']
if amount < min_price or amount > max_price:
# 如果是该用户第一次被标记为异常,则写入文件
if user_id in abnormal_users:
abnormal_file.write(f"{user_id},金额异常\n")
abnormal_users.remove(user_id) # 避免重复标记
break # 只要有一个异常就标记该用户,无需继续检查其他订单
# 银行卡异常
import re
from collections import defaultdict
from datetime import datetime
# 商品类型和价格范围映射
PRODUCT_PRICE_RANGES = {
'电子产品': (100, 5000),
'服装鞋包': (50, 1000),
'家居用品': (30, 2000),
'美妆护肤': (20, 800),
'食品饮料': (5, 300),
'图书文具': (5, 200),
'运动户外': (50, 3000)
}
# Luhn算法验证银行卡号
def luhn_check(card_number):
# 从右向左,偶数位数字乘以2
digits = [int(d) for d in card_number]
for i in range(len(digits) - 2, -1, -2):
doubled = digits[i] * 2
if doubled > 9:
doubled -= 9
digits[i] = doubled
# 计算总和
total = sum(digits)
# 总和能被10整除则有效
return total % 10 == 0
# 检查银行卡号是否符合格式和校验规则
def is_valid_card(card_number):
# 1. 长度要求: 16-19位数字
if not (16 <= len(card_number) <= 19):
return False
# 2. 字符要求: 仅包含数字字符
if not card_number.isdigit():
return False
# 3. Luhn算法验证
return luhn_check(card_number)
# 检查订单金额是否在商品类型的价格范围内
def is_valid_amount(product_type, amount):
if product_type not in PRODUCT_PRICE_RANGES:
return False
min_price, max_price = PRODUCT_PRICE_RANGES[product_type]
return min_price <= amount <= max_price
# 验证订单信息
def validate_order(order_line):
try:
# 解析每行信息
parts = order_line.strip().split(',')
if len(parts) != 9:
return False, f"字段数量不匹配,应为9个但实际有{len(parts)}个"
order_id, user_id, amount_str, order_time, product_type, payment_method, card_number, register_days, history_orders_str = parts
# 转换为对应的类型
amount = float(amount_str)
register_days = int(register_days)
history_orders = int(history_orders_str)
# 验证银行卡号
if not is_valid_card(card_number):
return False, "银行卡异常"
# 只有当所有验证都通过时才返回True
return True, "验证通过"
except Exception as e:
return False, f"解析失败: {str(e)}"
# 主函数
def main():
# 存储银行卡号使用情况(用于用户级检测)
card_usage_by_hour = defaultdict(list)
card_users = defaultdict(list) # 用于检测同一卡号在同一小时内被多个用户使用
valid_orders = [] # 有效的订单
invalid_orders = [] # 无效的订单
# 检查文件是否存在
try:
with open('data.txt', 'r', encoding='utf-8') as file:
lines = file.readlines()
# 先处理所有订单,收集银行卡使用信息
for line in lines:
if line.strip() == "":
continue
parts = line.strip().split(',')
if len(parts) != 9:
invalid_orders.append((parts[1], "字段数量不匹配"))
continue
order_id, user_id, amount_str, order_time, product_type, payment_method, card_number, register_days, history_orders_str = parts
try:
# 转换时间格式
order_time_dt = datetime.strptime(order_time, "%Y-%m-%d %H:%M:%S")
hour = order_time_dt.hour
# 收集银行卡使用情况
card_usage_by_hour[(card_number, hour)].append(user_id)
card_users[card_number].append(user_id)
except Exception as e:
pass # 如果时间解析出错,先忽略
# 然后进行实际验证
for line in lines:
if line.strip() == "":
continue
is_valid, reason = validate_order(line)
if not is_valid:
parts = line.strip().split(',')
user_id = parts[1]
invalid_orders.append((user_id, reason))
else:
# 如果有效,则添加到有效订单列表
valid_orders.append(line)
except FileNotFoundError:
print("订单文件 orders.txt 未找到")
return
# 检查银行卡号是否在同一小时内被多个用户使用(用户级异常检测)
for (card_number, hour), users in card_usage_by_hour.items():
if len(set(users)) > 1:
# 同一个卡号在同一小时内被多个不同的用户使用
# 这里简单地记录所有使用这个卡号的用户
for user in set(users):
# 如果这个用户的记录已经被标记为异常,则只保留一次
exists = any(user_id == user and reason == "银行卡异常" for user_id, reason in invalid_orders)
if not exists:
invalid_orders.append((user, "银行卡异常"))
# 将无效订单输出到文件
with open('1.txt', 'w', encoding='utf-8') as output_file:
for user_id, reason in invalid_orders:
output_file.write(f"{user_id},{reason}\n")
print(f"总订单数: {len(lines)}")
print(f"有效订单数: {len(valid_orders)}")
print(f"无效订单数: {len(invalid_orders)}")
# 运行主程序
if __name__ == "__main__":
main()
# 频率异常
import re
from collections import defaultdict
from datetime import datetime
import csv
# 商品类型与价格范围的映射
price_ranges = {
'电子产品': (100, 5000),
'服装鞋包': (50, 1000),
'家居用品': (30, 2000),
'美妆护肤': (20, 800),
'食品饮料': (5, 300),
'图书文具': (5, 200),
'运动户外': (50, 3000)
}
# 存储用户的订单列表
user_orders = defaultdict(list)
# 存储异常用户ID
abnormal_users = set()
# 存储用户异常类型记录
user_abnormal_records = defaultdict(set)
# 读取并处理文件
with open('data.txt', 'r', encoding='utf-8') as file:
for line_num, line in enumerate(file, 1):
line = line.strip()
if not line:
continue
try:
order_info = line.split(',')
# 检查字段数量是否正确
if len(order_info) != 9:
print(f"第{line_num}行字段数量不正确: {line}")
with open('1.txt', 'a', encoding='utf-8') as abnormal_file:
abnormal_file.write(f"未知,字段数异常\n")
continue
order_id, user_id, amount, timestamp, product_type, payment_method, bank_card, register_days, history_orders = order_info
# 验证金额格式是否为数字
try:
amount = float(amount)
except ValueError:
print(f"第{line_num}行金额格式错误: {amount}")
with open('1.txt', 'a', encoding='utf-8') as abnormal_file:
abnormal_file.write(f"{user_id},金额格式错误\n")
continue
# 检查商品类型是否存在
if product_type not in price_ranges:
print(f"第{line_num}行商品类型未定义: {product_type}")
with open('1.txt', 'a', encoding='utf-8') as abnormal_file:
abnormal_file.write(f"{user_id},商品类型异常\n")
continue
# 获取价格区间
min_price, max_price = price_ranges[product_type]
# 验证金额是否在正常范围内
if amount < min_price or amount > max_price:
print(f"第{line_num}行用户{user_id}的订单金额{amount}超出商品类型{product_type}的价格范围({min_price}到{max_price})")
abnormal_users.add(user_id)
user_abnormal_records[user_id].add('金额异常')
# 解析时间戳
try:
order_time = datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S')
except ValueError:
print(f"第{line_num}行时间戳格式错误: {timestamp}")
with open('1.txt', 'a', encoding='utf-8') as abnormal_file:
abnormal_file.write(f"{user_id},时间戳格式错误\n")
continue
# 将订单信息存入对应用户的列表中
user_orders[user_id].append({
'order_id': order_id,
'amount': amount,
'timestamp': order_time,
'product_type': product_type
})
except Exception as e:
print(f"处理第{line_num}行时出错: {line}")
with open('1.txt', 'a', encoding='utf-8') as abnormal_file:
abnormal_file.write(f"未知,解析错误\n")
# 排序各用户的所有订单(按时间)
for user_id in user_orders:
user_orders[user_id].sort(key=lambda x: x['timestamp'])
# 进行频率异常检测
user_window_orders = defaultdict(list)
for user_id, orders in user_orders.items():
# 按照时间窗口来分组统计每个窗口内的订单数
last_order_time = None
window_start = None
window_orders = []
for order in orders:
order_time = order['timestamp']
if last_order_time is None:
# 开始新窗口
window_start = order_time
window_orders = [order]
last_order_time = order_time
else:
# 如果当前订单与上一个订单时间差小于等于一小时,则加入窗口
time_diff = (order_time - last_order_time).total_seconds()
total_seconds = time_diff
if total_seconds <= 3600: # 一小时=3600秒
window_orders.append(order)
last_order_time = order_time
else:
# 如果当前订单与上一个订单时间差大于一小时,结束当前窗口
window_order_count = len(window_orders)
# 若窗口内订单数超过阈值10,则标记用户
if window_order_count > 10:
user_abnormal_records[user_id].add('频率异常')
# 开启新的窗口
window_start = order_time
window_orders = [order]
last_order_time = order_time
# 检查最后一个窗口
if window_orders:
window_order_count = len(window_orders)
if window_order_count > 10:
user_abnormal_records[user_id].add('频率异常')
# 将异常结果写入文件
with open('1.txt', 'w', encoding='utf-8') as abnormal_file: # 用 'w' 覆盖已有内容
for user_id, abnormal_types in user_abnormal_records.items():
for abnormal_type in abnormal_types:
abnormal_file.write(f"{user_id},{abnormal_type}\n")
print("异常检测完成,结果已写入 1.txt 文件")

评论已关闭