如何将SQLite .db转的二进制数据还原为.db文件(Python)
修复SQLite数据库隐写还原失败的问题
核心错误分析
- 编码逻辑冗余且错误:
你先将.db文件的二进制字节转成了二进制字符串(如01010011),随后又把这个字符串当成普通文本,将每个字符('0'或'1')转成ASCII字节的二进制形式存储。这相当于把原始数据库的二进制文本表示而非原始二进制数据隐藏到图片中,解码时自然只能得到二进制文本。 - 像素位处理不严谨:
使用bin(img_arr[i][j])[2:-1]提取像素高7位存在漏洞,比如像素值为0时,bin(0)返回'0b0',截取后得到空字符串,导致转换出错。 - 文件存在性检查未生效:
os.path.isfile()调用后没有判断返回值,无法检测文件是否真实存在。 - 解码逻辑与编码不匹配:
解码时错误地将提取的位转成字符再编码写入文件,完全对应了编码阶段的错误流程,无法还原原始二进制数据。
修正后的完整代码
import os import PIL.Image import numpy as np def steghide(): db_location = input("Enter the path to the .db file: ") try: if not os.path.isfile(db_location): raise FileNotFoundError(f"File {db_location} does not exist") with open(db_location, "rb") as file: content = file.read() # 直接将原始字节转成二进制位字符串,无需二次编码 binary_db = ''.join(f"{byte:08b}" for byte in content) except Exception as e: print("Error:", e) return # 出错后退出函数 img_location = input("Enter the path to the .png file: ") try: if not os.path.isfile(img_location): raise FileNotFoundError(f"File {img_location} does not exist") except Exception as e: print("Error:", e) return image = PIL.Image.open(img_location, 'r') width, height = image.size img_arr = np.array(list(image.getdata())) if image.mode == "P": print("Error: Paletted images not supported. ") return channels = 4 if image.mode == "RGBA" else 3 pixels = img_arr.size // channels indicator = "$STEGPASS$" # 将结束标识转成二进制位字符串,直接拼接到原始数据位后 indicator_bits = ''.join(f"{ord(c):08b}" for c in indicator) total_bits = binary_db + indicator_bits bits_len = len(total_bits) if bits_len > pixels * 3: # 每个像素用3个通道的最低位,所以总容量是pixels*3 print("Error: Not enough space within image.") return else: index = 0 for i in range(pixels): for j in range(3): # 只处理RGB三个通道,忽略Alpha if index < bits_len: # 用格式化字符串提取高7位,更可靠 pixel_bin = f"{img_arr[i][j]:08b}" # 替换最低位为隐藏的位 new_pixel_bin = pixel_bin[:7] + total_bits[index] img_arr[i][j] = int(new_pixel_bin, 2) index += 1 img_arr = img_arr.reshape((height, width, channels)) result = PIL.Image.fromarray(img_arr.astype('uint8'), image.mode) result.save('encoded.png') print("Encoding completed successfully!") def stegunhide(): img_location = input("Enter the path to the .png file: ") try: if not os.path.isfile(img_location): raise FileNotFoundError(f"File {img_location} does not exist") image = PIL.Image.open(img_location, 'r') img_arr = np.array(list(image.getdata())) if image.mode == "P": print("Error: Paletted images not supported. ") return channels = 4 if image.mode == "RGBA" else 3 pixels = img_arr.size // channels # 提取所有RGB通道的最低位 secret_bits = [] for i in range(pixels): for j in range(3): secret_bits.append(f"{img_arr[i][j]:08b}"[-1]) secret_bits = ''.join(secret_bits) # 先提取结束标识的二进制位,用于定位数据结尾 indicator = "$STEGPASS$" indicator_bits = ''.join(f"{ord(c):08b}" for c in indicator) indicator_len = len(indicator_bits) # 查找结束标识的位置 indicator_pos = secret_bits.find(indicator_bits) if indicator_pos == -1: print('Error: No database found.') return # 提取原始数据的位,转成字节 data_bits = secret_bits[:indicator_pos] # 确保位长度是8的倍数,避免截断错误 if len(data_bits) % 8 != 0: data_bits = data_bits[:-(len(data_bits) % 8)] # 将位字符串转成字节数组 db_content = bytes([int(data_bits[i:i+8], 2) for i in range(0, len(data_bits), 8)]) with open('decrypted.db', "wb") as file: file.write(db_content) print("Decoding completed successfully!") except Exception as e: print('Error:', e) # 可以根据需要调用函数 # steghide() # stegunhide()
关键修改说明
- 编码阶段:直接将.db文件的原始字节转成二进制位字符串,不再对二进制字符串做二次编码;修复像素位处理逻辑,确保高7位提取可靠;增加文件存在性的有效判断;修正容量计算(每个像素3个通道,总容量是
pixels*3位)。 - 解码阶段:直接提取位字符串后,定位结束标识的位置,将原始位字符串转成字节数组,直接写入文件,不再经过字符编码转换;增加位长度校验,避免因截断导致的字节错误。
内容的提问来源于stack exchange,提问作者alexis kouvakas
相关产品推荐
相关产品推荐

