日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

从nginx日志原始二进制数据还原文件

發布時間:2025/7/14 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从nginx日志原始二进制数据还原文件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

nginx的access日志自定義格式記錄了post請求數據,因為一些原因需要從原始數據恢復出jpg格式圖片。

首先處理日志,篩選出含有圖片數據的日志條目,取出其中一條進行分析,大致格式如下,為了便于查看,做一下換行處理:

- | 09/Dec/2017:08:00:19 +0000 | POST /some/api HTTP/1.1 | 200 | 461 | --SgX5AyE7dwyg0smH-Tqpt-ggGQwTU9 \x0D\x0AContent-Disposition: form-data; name=\x22name\x22\x0D\x0AContent-Type: text/plain; charset=UTF-8\x0D\x0A\x0D\x0value\x0D\x0A --SgX5AyE7dwyg0smH-Tqpt-ggGQwTU9 \x0D\x0AContent-Disposition: form-data; name=\x22file\x22; filename=\abc.jpg\x22 \x0D\x0AContent-Type: application/octet-stream \x0D\x0AContent-Transfer-Encoding: binary\x0D\x0A\x0D\x0A\xFF\xD8\xFF\xE0\x00\x10JFIF\x00 ... \xD2_\xA0\x1A\x7F\xFF\xD9\x0D\x0A --SgX5AyE7dwyg0smH-Tqpt-ggGQwTU9-- \x0D\x0A | 42097 | - | - | - | 1.1.1.1 | d1fkkbcd02eb | 127.0.0.1:8888 | 0.034 | 0.123

其中,--SgX5AyE7dwyg0smH-Tqpt-ggGQwTU9是表單的分隔字段,\x0D\x0A是回車和換行的轉義字符,分別等同于\r和\n,\xFF\xD8\xFF\xE0\x00\x10JFIF\x00 ... \xD2_\xA0\x1A\x7F\xFF\xD9部分就是圖片原始數據。

使用上述單行日志文件tmp.log進行調試:

>>> f = open('tmp.log', 'rb') >>> data = f.read() >>> data "- | 09/Dec/2017:08:00:19 +0000 | POST /some/api HTTP/1.1 | 200 | 461 | --SgX5AyE7dwyg0smH-Tqpt-ggGQwTU9\x0D\x0AContent-Disposition: form-data; name=\x22name\x22\x0D\x0AContent-Type: text/plain; charset=UTF-8\x0D\x0A\x0D\x0value\x0D\x0A--SgX5AyE7dwyg0smH-Tqpt-ggGQwTU9\x0D\x0AContent-Disposition: form-data; name=\x22file\x22; filename=\x221512806410245.jpg\x22\x0D\x0AContent-Type: application/octet-stream\x0D\x0AContent-Transfer-Encoding: binary\x0D\x0A\x0D\x0A\xFF\xD8\xFF\xE0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00 ... \xBC'\xF1\x8C\xCC\x83,\xFAo\xD2_\xA0\x1A\x7F\xFF\xD9 \x0D\x0A--SgX5AyE7dwyg0smH-Tqpt-ggGQwTU9--\x0D\x0A | 42097 | - | - | - | 1.1.1.1 | d1fkkbcd02eb | 127.0.0.1:8888 | 0.034 | 0.123" >>> print data - | 09/Dec/2017:08:00:19 +0000 | POST /some/api HTTP/1.1 | 200 | 461 | --SgX5AyE7dwyg0smH-Tqpt-ggGQwTU9\x0D\x0AContent-Disposition: form-data; name=\x22name\x22\x0D\x0AContent-Type: text/plain; charset=UTF-8\x0D\x0A\x0D\x0value\x0D\x0A--SgX5AyE7dwyg0smH-Tqpt-ggGQwTU9\x0D\x0AContent-Disposition: form-data; name=\x22file\x22; filename=\x221512806410245.jpg\x22\x0D\x0AContent-Type: application/octet-stream\x0D\x0AContent-Transfer-Encoding: binary\x0D\x0A\x0D\x0A\xFF\xD8\xFF\xE0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00 ... \xBC'\xF1\x8C\xCC\x83,\xFAo\xD2_\xA0\x1A\x7F\xFF\xD9\x0D\x0A--SgX5AyE7dwyg0smH-Tqpt-ggGQwTU9--\x0D\x0A | 42097 | - | - | - | 1.1.1.1 | d1fkkbcd02eb | 127.0.0.1:8888 | 0.034 | 0.123 >>> f.close()

可以看出,打印到屏幕上的轉義字符,如"\x0D\x0A"在文件中的原始字符串實際上是"\\x0D\\x0A"。因為""是用于轉義的,所以想要顯示反斜杠本身就必須轉義自身。也就是說,print的時候,"\"被轉義成"",所以我們看到的是"\x0D",實際文件中儲存的是"\\0D",而我們真正需要寫入文件的,是"\x0D"這個轉義字符,而不是"\x0D"這個字符串。

由于文件是以二進制方式打開的,讀取到的都是原始的流,所以在匹配的時候需要使用"\\\\"來表示"\\"。

使用re庫處理日志:

原始數據前面是Content-Transfer-Encoding: binary加上兩個\r\n,后面是一個\r\n跟上表單分割字符串--SgX5AyE7dwyg0smH-Tqpt-ggGQwTU9--

>>> import re >>> pf = re.compile('^.*Content-Transfer-Encoding: binary\\\\x0D\\\\x0A\\\\x0D\\\\x0A') >>> pb = re.compile('\\\\x0D\\\\x0A--.*$') >>> data = re.sub(pf,'',data) >>> data "\\xFF\\xD8\\xFF\\xE0\\x00\\x10JFIF\\x00\\x01\\x01\\x00\\x00\\x01\\x00 ... \\xBC'\\xF1\\x8C\\xCC\\x83,\\xFAo\\xD2_\\xA0\\x1A\\x7F\\xFF\\xD9\\x0D\\x0A--SgX5AyE7dwyg0smH-Tqpt-ggGQwTU9--\\x0D\\x0A | 42097 | - | - | - | 1.1.1.1 | d1fkkbcd02eb | 127.0.0.1:8888 | 0.034 | 0.123" >>> data = re.sub(pb,'',data) >>> data "\\xFF\\xD8\\xFF\\xE0\\x00\\x10JFIF\\x00\\x01\\x01\\x00\\x00\\x01\\x00 ... \\xBC'\\xF1\\x8C\\xCC\\x83,\\xFAo\\xD2_\\xA0\\x1A\\x7F\\xFF\\xD9"

這樣的匹配處理并不嚴謹,假設原始數據中本來就含有\\x0D\\x0A--的話,就會丟失原始數據,但目前為止還沒遇到這種情況有效。更麻煩的做法是先匹配出表單分割字符串,然后以此為界分割出數據后,再刪除兩邊多余的字符和回車換行。

成功提取出原始數據后,對數據進行解碼,并寫入.jpg文件。如果沒有解碼這一步,所有的數據都會被當做字符串寫入文件,而不會被當成轉義字符。簡單做個測試:

把"\xFF\xD8\xFF\xE0\x00\x10JFIF\x00\x01"保存到文件test.log。

>>> f = open('test.log', 'rb') >>> data = f.read() >>> data '\\xFF\\xD8\\xFF\\xE0\\x00\\x10JFIF\\x00\\x01\n' >>> print data \xFF\xD8\xFF\xE0\x00\x10JFIF\x00\x01>>> import codecs as c >>> c.decode(data, 'string_escape') '\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\n' >>> print c.decode(data, 'string_escape') ����JFIF>>>

讀取的原始數據是兩根反斜杠,print時因為反斜杠被轉義成字符,所以變成一根。解碼后的數據本身只有一根斜杠,print時打印出轉義字符本身,也就是亂碼。

接下來就可以分割文件,然后還原圖片了。

#!/usr/bin/env pythonimport codecs, reifile = 'access.log' suffix = 'jpg'pf = re.compile('^.*Content-Transfer-Encoding: binary\\\\x0D\\\\x0A\\\\x0D\\\\x0A') pb = re.compile('\\\\x0D\\\\x0A--.*$')try:with open(ifile, 'rb') as f:number = 1 #第一張圖片序號為1while True:l = f.readline().strip() #讀取一行并去掉末尾的換行符\nif not l: #文件讀完返回''時退出循環breakl = re.sub(pf, '', l) #將數據前的字符替換為空l = re.sub(pb, '', l) #將數據后的字符替換為空img_file = '.'.join([str(number), suffix]) #圖片文件名稱print img_file #打印名字方便看進度with open(img_file, 'wb') as i: #解碼并寫入文件i.write(codecs.decode(l, 'string_escape'))number += 1 #下一張圖片序號加1 except IOError:pass

access.log含有多條日志,每條日志都包含圖片數據。日志較大,所以不使用readlines(),本來使用list也很占內存,且這樣處理比較慢,要等程序把整個文件讀完。按行讀取日志后提取出圖片數據后解碼寫入文件即可。

在這里放一個demo日志,方便以后改進和調試。
https://files.cnblogs.com/files/nampp/demo.tar.gz

EOF

轉載于:https://www.cnblogs.com/nampp/p/8044085.html

總結

以上是生活随笔為你收集整理的从nginx日志原始二进制数据还原文件的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。