Pagbawi sa datos gikan sa XtraDB tables nga walay structure file gamit ang byte-by-byte analysis sa ibd file

Pagbawi sa datos gikan sa XtraDB tables nga walay structure file gamit ang byte-by-byte analysis sa ibd file

sa naunang kasaysayan

Nahitabo nga ang server giatake sa usa ka ransomware virus, nga, pinaagi sa usa ka "swerte nga aksidente," partially gibiyaan ang .ibd files (raw data files sa innodb tables) nga wala matandog, apan sa samang higayon hingpit nga na-encrypt ang .fpm files ( istruktura nga mga file). Niini nga kaso, ang .idb mahimong bahinon ngadto sa:

  • ubos sa pagpasig-uli pinaagi sa standard nga mga himan ug mga giya. Alang sa ingon nga mga kaso, adunay usa ka maayo kaayo mahimong;
  • partially encrypted nga mga lamesa. Kasagaran kini mga dagkong mga lamesa, diin (sa akong nasabtan) ang mga tig-atake walay igong RAM alang sa hingpit nga pag-encrypt;
  • Aw, bug-os nga naka-encrypt nga mga lamesa nga dili mapasig-uli.

Posible nga mahibal-an kung unsang kapilian ang nahisakop sa mga lamesa pinaagi lamang sa pag-abli niini sa bisan unsang editor sa teksto sa ilawom sa gusto nga pag-encode (sa akong kaso kini UTF8) ug yano nga pagtan-aw sa file alang sa presensya sa mga natad sa teksto, pananglitan:

Pagbawi sa datos gikan sa XtraDB tables nga walay structure file gamit ang byte-by-byte analysis sa ibd file

Usab, sa sinugdanan sa file mahimo nimong maobserbahan ang usa ka dako nga gidaghanon sa 0 bytes, ug ang mga virus nga naggamit sa block encryption algorithm (ang labing komon) kasagaran makaapekto usab kanila.
Pagbawi sa datos gikan sa XtraDB tables nga walay structure file gamit ang byte-by-byte analysis sa ibd file

Sa akong kaso, ang mga tig-atake nagbilin ug 4-byte string (1, 0, 0, 0) sa katapusan sa matag naka-encrypt nga file, nga nagpayano sa buluhaton. Aron makapangita sa wala ma-infect nga mga file, igo na ang script:

def opened(path):
    files = os.listdir(path)
    for f in files:
        if os.path.isfile(path + f):
            yield path + f

for full_path in opened("C:somepath"):
    file = open(full_path, "rb")
    last_string = ""
    for line in file:
        last_string = line
        file.close()
    if (last_string[len(last_string) -4:len(last_string)]) != (1, 0, 0, 0):
        print(full_path)

Sa ingon, nakit-an ang mga file nga nahisakop sa una nga tipo. Ang ikaduha naglakip sa daghang manwal nga trabaho, apan ang nakit-an igo na. Maayo ra ang tanan, apan kinahanglan nimo mahibal-an hingpit nga tukma nga istruktura ug (siyempre) mitungha ang usa ka kaso nga kinahanglan kong magtrabaho uban ang kanunay nga pag-ilis sa lamesa. Walay nakahinumdom kung giusab ba ang klase sa field o gidugang ang bag-ong column.

Ang Wilds City, sa walay palad, dili makatabang sa ingon nga kaso, mao nga kini nga artikulo gisulat.

Adto sa punto

Adunay usa ka istruktura sa usa ka lamesa gikan sa 3 ka bulan ang milabay nga dili motakdo sa karon (tingali usa ka uma, ug posible nga daghan pa). Istruktura sa lamesa:

CREATE TABLE `table_1` (
    `id` INT (11),
    `date` DATETIME ,
    `description` TEXT ,
    `id_point` INT (11),
    `id_user` INT (11),
    `date_start` DATETIME ,
    `date_finish` DATETIME ,
    `photo` INT (1),
    `id_client` INT (11),
    `status` INT (1),
    `lead__time` TIME ,
    `sendstatus` TINYINT (4)
); 

sa kini nga kaso, kinahanglan nimo nga kuhaon:

  • id_point int(11);
  • id_user int(11);
  • date_start PETSA;
  • date_finish DATETIME.

Alang sa pagbawi, gigamit ang usa ka byte-by-byte nga pagtuki sa .ibd file, gisundan sa pag-convert niini ngadto sa mas mabasa nga porma. Tungod kay aron makit-an kung unsa ang atong gikinahanglan, kinahanglan ra naton nga analisahon ang mga tipo sa datos sama sa int ug datatime, ang artikulo maghulagway lamang kanila, apan usahay maghisgot usab kita sa ubang mga tipo sa datos, nga makatabang sa ubang susama nga mga insidente.

Problema 1: mga natad nga adunay mga tipo nga DATETIME ug TEXT adunay NULL nga mga kantidad, ug kini gilaktawan ra sa file, tungod niini, dili posible nga mahibal-an ang istruktura nga ibalik sa akong kaso. Sa bag-ong mga kolum, ang default nga kantidad mao ang null, ug ang bahin sa transaksyon mahimong mawala tungod sa setting innodb_flush_log_at_trx_commit = 0, mao nga dugang nga oras ang kinahanglan igugol aron mahibal-an ang istruktura.

Problema 2: kinahanglan nga tagdon nga ang mga laray nga natangtang pinaagi sa DELETE maanaa tanan sa ibd file, apan sa ALTER TABLE ang ilang istruktura dili ma-update. Ingon usa ka sangputanan, ang istruktura sa datos mahimong magkalainlain gikan sa sinugdanan sa file hangtod sa katapusan niini. Kung kanunay nimo nga gigamit ang OPTIMIZE TABLE, nan dili nimo masugatan ang ingon nga problema.

Pagtagad, ang bersyon sa DBMS makaapekto sa paagi sa pagtipig sa datos, ug kini nga pananglitan mahimong dili magamit alang sa ubang dagkong mga bersyon. Sa akong kaso, ang bersyon sa windows sa mariadb 10.1.24 gigamit. Usab, bisan kung sa mariadb nagtrabaho ka sa mga lamesa sa InnoDB, sa tinuud sila XtraDB, nga wala maglakip sa paggamit sa pamaagi sa InnoDB mysql.

Pagtuki sa file

Sa python, tipo sa datos bytes() nagpakita sa Unicode data puli sa usa ka regular nga set sa mga numero. Bisan tuod mahimo nimong tan-awon ang payl niini nga porma, alang sa kasayon ​​mahimo nimong i-convert ang mga byte ngadto sa numeric nga porma pinaagi sa pag-convert sa byte array ngadto sa regular nga array (list(example_byte_array)). Sa bisan unsa nga kaso, ang duha nga mga pamaagi angay alang sa pagtuki.

Pagkahuman sa pagtan-aw sa daghang mga file sa ibd, makit-an nimo ang mosunod:

Pagbawi sa datos gikan sa XtraDB tables nga walay structure file gamit ang byte-by-byte analysis sa ibd file

Dugang pa, kung imong bahinon ang file sa kini nga mga keyword, makakuha ka kasagaran bisan mga bloke sa datos. Atong gamiton ang infimum isip divisor.

table = table.split("infimum".encode())

Usa ka makapaikag nga obserbasyon: alang sa mga lamesa nga adunay gamay nga kantidad sa datos, taliwala sa infimum ug supremum adunay usa ka pointer sa gidaghanon sa mga laray sa block.

Pagbawi sa datos gikan sa XtraDB tables nga walay structure file gamit ang byte-by-byte analysis sa ibd file — test table nga adunay 1st row

Pagbawi sa datos gikan sa XtraDB tables nga walay structure file gamit ang byte-by-byte analysis sa ibd file - test table nga adunay 2 ka laray

Ang row array table[0] mahimong laktawan. Pagkahuman sa pagtan-aw niini, wala gihapon nako makit-an ang hilaw nga datos sa lamesa. Lagmit, kini nga block gigamit sa pagtipig sa mga indeks ug mga yawe.
Sugod sa table[1] ug paghubad niini ngadto sa numeric array, mamatikdan na nimo ang pipila ka mga pattern, nga mao:

Pagbawi sa datos gikan sa XtraDB tables nga walay structure file gamit ang byte-by-byte analysis sa ibd file

Kini ang mga int value nga gitipigan sa usa ka string. Ang una nga byte nagpakita kung ang numero positibo o negatibo. Sa akong kaso, ang tanan nga mga numero positibo. Gikan sa nahabilin nga 3 bytes, mahimo nimong mahibal-an ang numero gamit ang mosunod nga function. Script:

def find_int(val: str):  # example '128, 1, 2, 3'
    val = [int(v) for v in  val.split(", ")]
    result_int = val[1]*256**2 + val[2]*256*1 + val[3]
    return result_int

Kay sa panig-ingnan, 128, 0, 0, 1 = 1, o 128, 0, 75, 108 = 19308.
Ang lamesa adunay usa ka panguna nga yawe nga adunay awtomatikong pagdugang, ug mahimo usab kini makit-an dinhi

Pagbawi sa datos gikan sa XtraDB tables nga walay structure file gamit ang byte-by-byte analysis sa ibd file

Sa pagtandi sa mga datos gikan sa mga lamesa sa pagsulay, gipadayag nga ang DATETIME nga butang naglangkob sa 5 bytes ug nagsugod sa 153 (lagmit nagpakita sa tinuig nga mga agwat). Tungod kay ang DATTIME range mao ang '1000-01-01' hangtod '9999-12-31', sa akong hunahuna ang gidaghanon sa mga byte mahimong magkalainlain, apan sa akong kaso, ang datos nahulog sa panahon gikan sa 2016 hangtod 2019, mao nga atong hunahunaon nga 5 bytes igo.

Aron mahibal-an ang oras nga wala’y mga segundo, ang mga musunod nga mga gimbuhaton gisulat. Script:

day_ = lambda x: x % 64 // 2  # {x,x,X,x,x }

def hour_(x1, x2):  # {x,x,X1,X2,x}
    if x1 % 2 == 0:
        return x2 // 16
    elif x1 % 2 == 1:
        return x2 // 16 + 16
    else:
        raise ValueError

min_ = lambda x1, x2: (x1 % 16) * 4 + (x2 // 64)  # {x,x,x,X1,X2}

Dili mahimo ang pagsulat sa usa ka functional function alang sa tuig ug bulan, mao nga kinahanglan nako nga i-hack kini. Script:

ym_list = {'2016, 1': '153, 152, 64', '2016, 2': '153, 152, 128', 
           '2016, 3': '153, 152, 192', '2016, 4': '153, 153, 0',
           '2016, 5': '153, 153, 64', '2016, 6': '153, 153, 128', 
           '2016, 7': '153, 153, 192', '2016, 8': '153, 154, 0', 
           '2016, 9': '153, 154, 64', '2016, 10': '153, 154, 128', 
           '2016, 11': '153, 154, 192', '2016, 12': '153, 155, 0',
           '2017, 1': '153, 155, 128', '2017, 2': '153, 155, 192', 
           '2017, 3': '153, 156, 0', '2017, 4': '153, 156, 64',
           '2017, 5': '153, 156, 128', '2017, 6': '153, 156, 192',
           '2017, 7': '153, 157, 0', '2017, 8': '153, 157, 64',
           '2017, 9': '153, 157, 128', '2017, 10': '153, 157, 192', 
           '2017, 11': '153, 158, 0', '2017, 12': '153, 158, 64', 
           '2018, 1': '153, 158, 192', '2018, 2': '153, 159, 0',
           '2018, 3': '153, 159, 64', '2018, 4': '153, 159, 128', 
           '2018, 5': '153, 159, 192', '2018, 6': '153, 160, 0',
           '2018, 7': '153, 160, 64', '2018, 8': '153, 160, 128',
           '2018, 9': '153, 160, 192', '2018, 10': '153, 161, 0', 
           '2018, 11': '153, 161, 64', '2018, 12': '153, 161, 128',
           '2019, 1': '153, 162, 0', '2019, 2': '153, 162, 64', 
           '2019, 3': '153, 162, 128', '2019, 4': '153, 162, 192', 
           '2019, 5': '153, 163, 0', '2019, 6': '153, 163, 64',
           '2019, 7': '153, 163, 128', '2019, 8': '153, 163, 192',
           '2019, 9': '153, 164, 0', '2019, 10': '153, 164, 64', 
           '2019, 11': '153, 164, 128', '2019, 12': '153, 164, 192',
           '2020, 1': '153, 165, 64', '2020, 2': '153, 165, 128',
           '2020, 3': '153, 165, 192','2020, 4': '153, 166, 0', 
           '2020, 5': '153, 166, 64', '2020, 6': '153, 1, 128',
           '2020, 7': '153, 166, 192', '2020, 8': '153, 167, 0', 
           '2020, 9': '153, 167, 64','2020, 10': '153, 167, 128',
           '2020, 11': '153, 167, 192', '2020, 12': '153, 168, 0'}

def year_month(x1, x2):  # {x,X,X,x,x }

    for key, value in ym_list.items():
        key = [int(k) for k in key.replace("'", "").split(", ")]
        value = [int(v) for v in value.split(", ")]
        if x1 == value[1] and x2 // 64 == value[2] // 64:
            return key
    return 0, 0

Sigurado ako nga kung mogugol ka ug daghang oras, kini nga dili pagsinabtanay mahimong matul-id.
Sunod, usa ka function nga nagbalik sa usa ka datetime nga butang gikan sa usa ka string. Script:

def find_data_time(val:str):
    val = [int(v) for v in val.split(", ")]
    day = day_(val[2])
    hour = hour_(val[2], val[3])
    minutes = min_(val[3], val[4])
    year, month = year_month(val[1], val[2])
    return datetime(year, month, day, hour, minutes)

Nahimo nga makit-an ang kanunay nga gibalikbalik nga mga kantidad gikan sa int, int, datetime, datetime Pagbawi sa datos gikan sa XtraDB tables nga walay structure file gamit ang byte-by-byte analysis sa ibd file, murag mao ni ang imong gikinahanglan. Dugang pa, ang ingon nga pagkasunod-sunod dili gisubli kaduha matag linya.

Gamit ang usa ka regular nga ekspresyon, atong makita ang gikinahanglan nga datos:

fined = re.findall(r'128, d*, d*, d*, 128, d*, d*, d*, 153, 1[6,5,4,3]d, d*, d*, d*, 153, 1[6,5,4,3]d, d*, d*, d*', int_array)

Palihug timan-i nga kung nangita gamit kini nga ekspresyon, dili posible nga mahibal-an ang NULL nga mga kantidad sa gikinahanglan nga mga natad, apan sa akong kaso dili kini kritikal. Dayon among giagian ang among nakit-an sa usa ka loop. Script:

result = []
for val in fined:
    pre_result = []
    bd_int  = re.findall(r"128, d*, d*, d*", val)
    bd_date= re.findall(r"(153, 1[6,5,4,3]d, d*, d*, d*)", val)
    for it in bd_int:
        pre_result.append(find_int(bd_int[it]))
    for bd in bd_date:
        pre_result.append(find_data_time(bd))
    result.append(pre_result)

Sa tinuud, mao ra kana, ang datos gikan sa han-ay sa resulta mao ang datos nga kinahanglan namon. ##PS.##
Nasabtan nako nga kini nga pamaagi dili angay alang sa tanan, apan ang panguna nga katuyoan sa artikulo mao ang pag-aghat sa aksyon kaysa pagsulbad sa tanan nimong mga problema. Sa akong hunahuna ang labing husto nga solusyon mao ang pagsugod sa pagtuon sa source code sa imong kaugalingon mariadb, apan tungod sa limitado nga panahon, ang kasamtangan nga pamaagi daw mao ang labing paspas.

Sa pipila ka mga kaso, pagkahuman sa pag-analisar sa file, mahimo nimong mahibal-an ang gibanabana nga istruktura ug ibalik kini gamit ang usa sa mga sumbanan nga pamaagi gikan sa mga link sa ibabaw. Kini mahimong mas husto ug hinungdan sa mas gamay nga mga problema.

Source: www.habr.com

Idugang sa usa ka comment