ibd ఫైల్ యొక్క బైట్-బై-బైట్ విశ్లేషణను ఉపయోగించి స్ట్రక్చర్ ఫైల్ లేకుండా XtraDB పట్టికల నుండి డేటాను పునరుద్ధరించడం

ibd ఫైల్ యొక్క బైట్-బై-బైట్ విశ్లేషణను ఉపయోగించి స్ట్రక్చర్ ఫైల్ లేకుండా XtraDB పట్టికల నుండి డేటాను పునరుద్ధరించడం

పూర్వచరిత్ర

సర్వర్‌పై ransomware వైరస్ దాడి జరిగింది, ఇది "లక్కీ యాక్సిడెంట్" ద్వారా .ibd ఫైల్‌లను (innodb టేబుల్‌ల యొక్క ముడి డేటా ఫైల్‌లు) పాక్షికంగా తాకబడలేదు, కానీ అదే సమయంలో .fpm ఫైల్‌లను పూర్తిగా ఎన్‌క్రిప్ట్ చేసింది ( స్ట్రక్చర్ ఫైల్స్). ఈ సందర్భంలో, .idbని ఇలా విభజించవచ్చు:

  • ప్రామాణిక సాధనాలు మరియు మార్గదర్శకాల ద్వారా పునరుద్ధరణకు లోబడి ఉంటుంది. అటువంటి సందర్భాలలో, ఒక అద్భుతమైన ఉంది అవుతాయి;
  • పాక్షికంగా గుప్తీకరించిన పట్టికలు. ఎక్కువగా ఇవి పెద్ద పట్టికలు, దీని కోసం (నేను అర్థం చేసుకున్నట్లుగా) దాడి చేసేవారికి పూర్తి ఎన్‌క్రిప్షన్ కోసం తగినంత RAM లేదు;
  • బాగా, పూర్తిగా గుప్తీకరించిన పట్టికలు పునరుద్ధరించబడవు.

ఏదైనా టెక్స్ట్ ఎడిటర్‌లో కావలసిన ఎన్‌కోడింగ్‌లో (నా విషయంలో ఇది UTF8) తెరవడం ద్వారా మరియు టెక్స్ట్ ఫీల్డ్‌ల ఉనికి కోసం ఫైల్‌ను వీక్షించడం ద్వారా పట్టికలు ఏ ఎంపికకు చెందినవో గుర్తించడం సాధ్యమైంది, ఉదాహరణకు:

ibd ఫైల్ యొక్క బైట్-బై-బైట్ విశ్లేషణను ఉపయోగించి స్ట్రక్చర్ ఫైల్ లేకుండా XtraDB పట్టికల నుండి డేటాను పునరుద్ధరించడం

అలాగే, ఫైల్ ప్రారంభంలో మీరు పెద్ద సంఖ్యలో 0 బైట్‌లను గమనించవచ్చు మరియు బ్లాక్ ఎన్‌క్రిప్షన్ అల్గోరిథం (అత్యంత సాధారణం) ఉపయోగించే వైరస్‌లు సాధారణంగా వాటిని కూడా ప్రభావితం చేస్తాయి.
ibd ఫైల్ యొక్క బైట్-బై-బైట్ విశ్లేషణను ఉపయోగించి స్ట్రక్చర్ ఫైల్ లేకుండా XtraDB పట్టికల నుండి డేటాను పునరుద్ధరించడం

నా విషయంలో, దాడి చేసేవారు ప్రతి గుప్తీకరించిన ఫైల్ చివరిలో 4-బైట్ స్ట్రింగ్‌ను (1, 0, 0, 0) వదిలివేశారు, ఇది పనిని సులభతరం చేసింది. వ్యాధి సోకని ఫైల్‌ల కోసం శోధించడానికి, స్క్రిప్ట్ సరిపోతుంది:

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)

అందువలన, ఇది మొదటి రకానికి చెందిన ఫైళ్లను కనుగొనడానికి మారినది. రెండవది చాలా మాన్యువల్ పనిని కలిగి ఉంటుంది, కానీ కనుగొనబడినది ఇప్పటికే సరిపోతుంది. అంతా బాగానే ఉంటుంది, కానీ మీరు తెలుసుకోవాలి ఖచ్చితంగా ఖచ్చితమైన నిర్మాణం మరియు (వాస్తవానికి) నేను తరచుగా మారుతున్న పట్టికతో పని చేయాల్సి వచ్చింది. ఫీల్డ్ రకం మార్చబడిందా లేదా కొత్త కాలమ్ జోడించబడిందో ఎవరికీ గుర్తులేదు.

వైల్డ్స్ సిటీ, దురదృష్టవశాత్తు, అటువంటి సందర్భంలో సహాయం చేయలేకపోయింది, అందుకే ఈ వ్యాసం వ్రాయబడుతోంది.

పాయింట్ పొందండి

3 నెలల క్రితం నుండి ఒక టేబుల్ నిర్మాణం ఉంది, అది ప్రస్తుత దానితో (బహుశా ఒక ఫీల్డ్, మరియు బహుశా ఎక్కువ) ఏకీభవించదు. పట్టిక నిర్మాణం:

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)
); 

ఈ సందర్భంలో, మీరు సంగ్రహించవలసి ఉంటుంది:

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

రికవరీ కోసం, .ibd ఫైల్ యొక్క బైట్-బై-బైట్ విశ్లేషణ ఉపయోగించబడుతుంది, తర్వాత వాటిని మరింత చదవగలిగే రూపంలోకి మార్చడం జరుగుతుంది. మనకు అవసరమైన వాటిని కనుగొనడానికి, మేము Int మరియు datatime వంటి డేటా రకాలను మాత్రమే విశ్లేషించాలి, వ్యాసం వాటిని మాత్రమే వివరిస్తుంది, కానీ కొన్నిసార్లు మేము ఇతర డేటా రకాలను కూడా సూచిస్తాము, ఇది ఇతర సారూప్య సంఘటనలలో సహాయపడుతుంది.

సమస్య 1: DATETIME మరియు TEXT రకాలు గల ఫీల్డ్‌లు NULL విలువలను కలిగి ఉన్నాయి మరియు అవి ఫైల్‌లో దాటవేయబడతాయి, దీని కారణంగా, నా విషయంలో పునరుద్ధరించడానికి నిర్మాణాన్ని గుర్తించడం సాధ్యం కాలేదు. కొత్త నిలువు వరుసలలో, డిఫాల్ట్ విలువ శూన్యం మరియు innodb_flush_log_at_trx_commit = 0 సెట్టింగ్ కారణంగా లావాదేవీలో కొంత భాగాన్ని కోల్పోవచ్చు, కాబట్టి నిర్మాణాన్ని గుర్తించడానికి అదనపు సమయాన్ని వెచ్చించాల్సి ఉంటుంది.

సమస్య 2: DELETE ద్వారా తొలగించబడిన అడ్డు వరుసలు అన్నీ ibd ఫైల్‌లో ఉంటాయని పరిగణనలోకి తీసుకోవాలి, కానీ ALTER TABLEతో వాటి నిర్మాణం నవీకరించబడదు. ఫలితంగా, డేటా నిర్మాణం ఫైల్ ప్రారంభం నుండి దాని ముగింపు వరకు మారవచ్చు. మీరు తరచుగా ఆప్టిమైజ్ టేబుల్‌ని ఉపయోగిస్తుంటే, మీరు అలాంటి సమస్యను ఎదుర్కొనే అవకాశం లేదు.

శ్రద్ద, DBMS సంస్కరణ డేటా నిల్వ చేయబడే విధానాన్ని ప్రభావితం చేస్తుంది మరియు ఈ ఉదాహరణ ఇతర ప్రధాన సంస్కరణలకు పని చేయకపోవచ్చు. నా విషయంలో, mariadb 10.1.24 యొక్క విండోస్ వెర్షన్ ఉపయోగించబడింది. అలాగే, mariadbలో మీరు InnoDB పట్టికలతో పని చేస్తున్నప్పటికీ, నిజానికి అవి ఎక్స్‌ట్రాడిబి, ఇది InnoDB mysqlతో పద్ధతి యొక్క అనువర్తనాన్ని మినహాయిస్తుంది.

ఫైల్ విశ్లేషణ

పైథాన్‌లో, డేటా రకం బైట్లు() సాధారణ సంఖ్యల సెట్ స్థానంలో యూనికోడ్ డేటాను ప్రదర్శిస్తుంది. మీరు ఈ ఫారమ్‌లో ఫైల్‌ను వీక్షించగలిగినప్పటికీ, సౌలభ్యం కోసం మీరు బైట్ శ్రేణిని సాధారణ శ్రేణిగా మార్చడం ద్వారా బైట్‌లను సంఖ్యా రూపంలోకి మార్చవచ్చు (list(example_byte_array)). ఏదైనా సందర్భంలో, రెండు పద్ధతులు విశ్లేషణకు అనుకూలంగా ఉంటాయి.

అనేక ibd ఫైల్‌లను చూసిన తర్వాత, మీరు ఈ క్రింది వాటిని కనుగొనవచ్చు:

ibd ఫైల్ యొక్క బైట్-బై-బైట్ విశ్లేషణను ఉపయోగించి స్ట్రక్చర్ ఫైల్ లేకుండా XtraDB పట్టికల నుండి డేటాను పునరుద్ధరించడం

అంతేకాకుండా, మీరు ఈ కీలక పదాలతో ఫైల్‌ను విభజించినట్లయితే, మీరు ఎక్కువగా డేటా బ్లాక్‌లను కూడా పొందుతారు. మేము ఇన్ఫిమమ్‌ను డివైజర్‌గా ఉపయోగిస్తాము.

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

ఒక ఆసక్తికరమైన పరిశీలన: తక్కువ మొత్తంలో డేటా ఉన్న పట్టికల కోసం, ఇన్ఫిమమ్ మరియు సుప్రీమమ్ మధ్య బ్లాక్‌లోని అడ్డు వరుసల సంఖ్యకు పాయింటర్ ఉంటుంది.

ibd ఫైల్ యొక్క బైట్-బై-బైట్ విశ్లేషణను ఉపయోగించి స్ట్రక్చర్ ఫైల్ లేకుండా XtraDB పట్టికల నుండి డేటాను పునరుద్ధరించడం - 1వ వరుసతో పరీక్ష పట్టిక

ibd ఫైల్ యొక్క బైట్-బై-బైట్ విశ్లేషణను ఉపయోగించి స్ట్రక్చర్ ఫైల్ లేకుండా XtraDB పట్టికల నుండి డేటాను పునరుద్ధరించడం - 2 వరుసలతో పరీక్ష పట్టిక

అడ్డు వరుస శ్రేణి పట్టిక[0] దాటవేయబడవచ్చు. దాని ద్వారా చూసిన తర్వాత, నేను ఇప్పటికీ ముడి పట్టిక డేటాను కనుగొనలేకపోయాను. చాలా మటుకు, ఈ బ్లాక్ సూచికలు మరియు కీలను నిల్వ చేయడానికి ఉపయోగించబడుతుంది.
పట్టిక[1]తో ప్రారంభించి, దానిని సంఖ్యా శ్రేణిలోకి అనువదించడం ద్వారా, మీరు ఇప్పటికే కొన్ని నమూనాలను గమనించవచ్చు, అవి:

ibd ఫైల్ యొక్క బైట్-బై-బైట్ విశ్లేషణను ఉపయోగించి స్ట్రక్చర్ ఫైల్ లేకుండా XtraDB పట్టికల నుండి డేటాను పునరుద్ధరించడం

ఇవి స్ట్రింగ్‌లో నిల్వ చేయబడిన పూర్ణాంక విలువలు. మొదటి బైట్ సంఖ్య సానుకూలమైనదా లేదా ప్రతికూలమైనదా అని సూచిస్తుంది. నా విషయంలో, అన్ని సంఖ్యలు సానుకూలంగా ఉన్నాయి. మిగిలిన 3 బైట్‌ల నుండి, మీరు క్రింది ఫంక్షన్‌ని ఉపయోగించి సంఖ్యను నిర్ణయించవచ్చు. స్క్రిప్ట్:

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

ఉదాహరణకు, 128, 0, 0, 1 = 1లేదా 128, 0, 75, 108 = 19308.
పట్టిక స్వీయ-పెంపుతో ప్రాథమిక కీని కలిగి ఉంది మరియు దానిని ఇక్కడ కూడా కనుగొనవచ్చు

ibd ఫైల్ యొక్క బైట్-బై-బైట్ విశ్లేషణను ఉపయోగించి స్ట్రక్చర్ ఫైల్ లేకుండా XtraDB పట్టికల నుండి డేటాను పునరుద్ధరించడం

పరీక్ష పట్టికల నుండి డేటాను పోల్చిన తర్వాత, DATETIME ఆబ్జెక్ట్ 5 బైట్‌లను కలిగి ఉందని మరియు 153తో ప్రారంభమైందని వెల్లడైంది (చాలా మటుకు వార్షిక విరామాలను సూచిస్తుంది). DATTIME పరిధి '1000-01-01' నుండి '9999-12-31' వరకు ఉన్నందున, బైట్‌ల సంఖ్య మారవచ్చు అని నేను అనుకుంటున్నాను, కానీ నా విషయంలో, డేటా 2016 నుండి 2019 వరకు ఉంటుంది కాబట్టి మేము ఊహిస్తాము 5 బైట్లు సరిపోతాయి.

సెకన్లు లేకుండా సమయాన్ని నిర్ణయించడానికి, కింది విధులు వ్రాయబడ్డాయి. స్క్రిప్ట్:

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}

సంవత్సరం మరియు నెల కోసం ఫంక్షనల్ ఫంక్షన్ రాయడం సాధ్యం కాదు, కాబట్టి నేను దానిని హ్యాక్ చేయాల్సి వచ్చింది. స్క్రిప్ట్:

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

మీరు ఎక్కువ సమయం వెచ్చిస్తే, ఈ అపార్థాన్ని సరిదిద్దవచ్చని నేను ఖచ్చితంగా అనుకుంటున్నాను.
తర్వాత, స్ట్రింగ్ నుండి డేట్‌టైమ్ ఆబ్జెక్ట్‌ని అందించే ఫంక్షన్. స్క్రిప్ట్:

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)

Int, int, datetime, datetime నుండి తరచుగా పునరావృతమయ్యే విలువలను గుర్తించడం నిర్వహించబడుతుంది ibd ఫైల్ యొక్క బైట్-బై-బైట్ విశ్లేషణను ఉపయోగించి స్ట్రక్చర్ ఫైల్ లేకుండా XtraDB పట్టికల నుండి డేటాను పునరుద్ధరించడం, ఇది మీకు కావాల్సిందిగా కనిపిస్తోంది. అంతేకాకుండా, అటువంటి క్రమం ఒక పంక్తికి రెండుసార్లు పునరావృతం కాదు.

సాధారణ వ్యక్తీకరణను ఉపయోగించి, మేము అవసరమైన డేటాను కనుగొంటాము:

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)

ఈ వ్యక్తీకరణను ఉపయోగించి శోధిస్తున్నప్పుడు, అవసరమైన ఫీల్డ్‌లలో NULL విలువలను గుర్తించడం సాధ్యం కాదని దయచేసి గమనించండి, కానీ నా విషయంలో ఇది క్లిష్టమైనది కాదు. అప్పుడు మనం లూప్‌లో కనుగొన్న దాని ద్వారా వెళ్తాము. స్క్రిప్ట్:

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)

వాస్తవానికి, అంతే, ఫలిత శ్రేణిలోని డేటా మనకు అవసరమైన డేటా. ###PS.###
ఈ పద్ధతి అందరికీ సరిపోదని నేను అర్థం చేసుకున్నాను, అయితే వ్యాసం యొక్క ప్రధాన లక్ష్యం మీ సమస్యలన్నింటినీ పరిష్కరించే బదులు చర్య తీసుకోవడమే. సోర్స్ కోడ్‌ను మీరే అధ్యయనం చేయడం ప్రారంభించడమే సరైన పరిష్కారం అని నేను భావిస్తున్నాను MariaDB, కానీ పరిమిత సమయం కారణంగా, ప్రస్తుత పద్ధతి అత్యంత వేగవంతమైనదిగా అనిపించింది.

కొన్ని సందర్భాల్లో, ఫైల్‌ను విశ్లేషించిన తర్వాత, మీరు సుమారుగా నిర్మాణాన్ని గుర్తించగలరు మరియు ఎగువ లింక్‌ల నుండి ప్రామాణిక పద్ధతుల్లో ఒకదానిని ఉపయోగించి దాన్ని పునరుద్ధరించగలరు. ఇది చాలా సరైనది మరియు తక్కువ సమస్యలను కలిగిస్తుంది.

మూలం: www.habr.com

ఒక వ్యాఖ్యను జోడించండి