(昨天没写完,今天继续。我明明只是保存为草稿,怎么自动发布了,这是咋回事?)
二、内核程序
进行一些输入操作,发现有个5个指令,但只有help/ls/wr是可以使用的。
继续用IDA分析,但为了方便分析,对原镜像中第2-5个扇区用1337进行异或解密,同时为了使设置加载地址为0x07C00时,第二个扇区能在0×08000地址处(字符串偏移对了就不自己再计算了)。因此我在镜像中第一个扇区后增加一个空扇区。
内核程序先做了下初始化(交换了中断向量表中10h和13h内容,将0:90F0h的内容设置为0A00h),之后显示了logo,进入main过程中。(这些是异或解密后的代码)
在main过程中,先显示提示输入符(user@bctf#),之后接受输入指令,再调用cmd过程处理所输入指令。
在cmd过程中,通过字节比较后执行相应的指令(help/wr/ls/rd/dl)。rd/dl只是简单回显'Error: Permission deny!',help/ls也差不多,主要看wr的处理过程:
1)验证文件名是否合理(长度小于23),
2)根据时间戳生成一个[min, max)范围中的随机数(这个gen_number很重要,后面经常见到它),这里的随机数我们记录为key,后面会用它来加密文件内容。
3)显示提示信息,接受输入
文件结束输入后,调用两个最重要的过程(create_fileheader, savefile)来保存文件到磁盘中。
create_fileheader:创建文件信息头,并保存在0面1磁道1扇区(0x7e00开始,一共8个扇区),savefile保存文件内容。
文件信息头,保存的文件内容结构的结构如下,这构成一条文件链,由结构里的header/cylinder/sector/index找到下一个节点的信息,依次连接起来;当header/cylinder/sector/index都为0xFF时结束。
struct fileheader{ word isExist; //1表示该块已经使用,否则为0 word filelength; word key; byte header; //磁头 byte cylinder; //磁道 byte index; //这里将一个扇区分成16个小块,每块32个字节 byte sector; //扇区 byte[22] encrypt_filename; //采用异或0xCC加密 } struct filecontent{ word isExist; //1表示该块已经使用,否则为0 byte header; byte cylinder; byte index; byte sector; byte[26] encrypt_filecontent; //采用异或key再异或字符下标加密 }
简单看下,还是通过gen_number生成随机的header/cylinder/sector/index,然后调用filecheck检查该块是否已经使用。如果已经使用,通过加1调整。
class ReadFile(object): def __init__(self, file): self.fin = file def read(self, offset): self.filename = '' self.content = [] self.key = 0 self.__getContent(offset, True) return self.__decode() def __getOffset(self, hander, cylinder, sector, index): return ((hander+2*cylinder)*63+sector-1)*512+index*32 def __getContent(self, offset, isHeader=False): if isHeader: self.fin.seek(offset+5) self.key = ord(self.fin.read(1)) else: self.fin.seek(offset+2) header = ord(self.fin.read(1)) cylinder = ord(self.fin.read(1)) index = ord(self.fin.read(1)) sector = ord(self.fin.read(1)) if isHeader: self.filename = self.fin.read(22) else: self.content.append(self.fin.read(26)) if header != 255: self.__getContent(self.__getOffset(header, cylinder, sector, index)) def __decode(self): name = [chr(ord(ch)^0xCC) for ch in self.filename if ord(ch) != 0] content = [chr(ord(ch)^self.key^i) for i, ch in enumerate(''.join(self.content))] return 'read file:%s\n%s' % (''.join(name), ''.join(content)) if __name__ == '__main__': fin = open('bctfos.bin', 'rb') rd = ReadFile(fin) print rd.read(0x7e00) fin.close()
key
read file:key Dear CTFer, if you see this message, you have completely understood my OS. Congratulations!Here is what you want: BCTF{6e4636cd8bcfa93213c83f4b8314ef00}
over, thanks.