import os.path dbfilename="test.db" f=file(dbfilename,"rb") fout=file("out.db","wb") def readpage(f,ind): f.seek(ind*0x400) return f.read(0x400) def recover(dat): lenmap={} cleanpos=ord(dat[1])*0x100+ord(dat[2]) if cleanpos==0: return dat newdat = bytearray(dat) newdat[1]=0 newdat[2]=0 recovnode=[] while cleanpos!=0: nextpos=ord(dat[cleanpos])*0x100+ord(dat[cleanpos+1]) datlen=ord(dat[cleanpos+3]) for n in xrange(4,datlen): if dat[cleanpos+n]==dat[cleanpos] and dat[cleanpos+n+1]==dat[cleanpos+1]: nextpos=cleanpos+n datlen=nextpos-cleanpos break recovnode.append(cleanpos) lenmap[cleanpos]=datlen newdat[cleanpos]=datlen newdat[cleanpos+1]=0 newdat[cleanpos+2]=newdat[cleanpos]-4 newdat[cleanpos+2]=0 cleanpos=nextpos reccnt=ord(dat[3])*0x100+ord(dat[4]) recstart=ord(dat[5])*0x100+ord(dat[6]) for i in xrange(0,reccnt): datpos=ord(dat[8+2*i])*0x100+ord(dat[9+2*i]) lenmap[datpos]=ord(dat[datpos])+2 recovnode.append(datpos) firstrec=ord(dat[8+2*reccnt])*0x100+ord(dat[9+2*reccnt]) cleanpos=firstrec while cleanpos!=0 and cleanpos<0x400: if cleanpos in recovnode: cleanpos+=lenmap[cleanpos] continue nextpos=cleanpos+ord(dat[cleanpos+2])*0x100+ord(dat[cleanpos+3]) lenmap[cleanpos]=ord(dat[cleanpos+3]) recovnode.append(cleanpos) newdat[cleanpos]=ord(dat[cleanpos+3])-2 cleanpos=nextpos recovnode.sort() recovnode.reverse() idcnt=0 newdat[3]=len(recovnode)>>8 newdat[4]=len(recovnode)&0xff newdat[5]=recovnode[-1]>>8 newdat[6]=recovnode[-1]&0xff for node in recovnode: newdat[8+2*idcnt]=node>>8 newdat[9+2*idcnt]=node&0xff idcnt+=1 newdat[node]=lenmap[node]-2 newdat[node+1]=idcnt newdat[node+2]=4 newdat[node+3]=0 return newdat dat=readpage(f,0) fout.write(dat) for ind in xrange(1,os.path.getsize(dbfilename)/0x400): dat=readpage(f,ind) fout.write(recover(dat))
实验步骤:
D:\lzf\dbrecover>sqlite3 test.db sqlite version 3.7.11 2012-03-20 11:35:50 Enter ".help" for instructions Enter sql statements terminated with a ";" sqlite> .echo on sqlite> .read test.sql .read test.sql CREATE TABLE test (_id INTEGER PRIMARY KEY AUTOINCREMENT,nameid Integer,name text); INSERT INTO test (nameid,name) VALUES (1,"lzf"); INSERT INTO test (nameid,name) VALUES (2,"luozf"); INSERT INTO test (nameid,name) VALUES (3,"lzhif"); INSERT INTO test (nameid,name) VALUES (4,"lzfan"); INSERT INTO test (nameid,name) VALUES (5,"l"); INSERT INTO test (nameid,name) VALUES (6,"zephyrluo"); INSERT INTO test (nameid,name) VALUES (7,"2B"); DELETE FROM test WHERE nameid=1 OR nameid=3 OR nameid=7 OR nameid=4 or nameid=2; sqlite> select * from test; select * from test; 5|5|l 6|6|zephyrluo sqlite> .exit .exit D:\lzf\dbrecover>recovery.py D:\lzf\dbrecover>sqlite3 out.db sqlite version 3.7.11 2012-03-20 11:35:50 Enter ".help" for instructions Enter sql statements terminated with a ";" sqlite> select * from test; 1|1|lzf 2|2|luozf 3|3|lzhif 4|4|lzfan 5|5|l 6|6|zephyrluo 7|7|2B