0%

补题:Strange_int

strange int

strange_int

打国赛的时候没做出来这道题,现在看了题解来补一补

思路

开始

以前写过FAT16的模拟程序,看到这个文件第一想法是这是一个DBR

第一行的 jmp 就是 jump 到这个命令的下一个命令。。

seg000:0000                 jmp     far ptr 7C0h:5
seg000:0005 ; ---------------------------------------------------------------------------
seg000:0005 mov ax, cs
seg000:0007 mov ds, ax
seg000:0009 mov ss, ax
seg000:000B mov sp, 400h
seg000:000E cld
seg000:000F mov ax, 3
seg000:0012 int 10h ; - VIDEO - SET VIDEO MODE
seg000:0012 ; AL = mode
seg000:0014 mov dx, 0
seg000:0017 mov cx, 2
seg000:001A mov ax, 1000h
seg000:001D mov es, ax
seg000:001F assume es:nothing
seg000:001F xor bx, bx
seg000:0021 mov ax, 228h
seg000:0024 int 13h ; DISK - READ SECTORS INTO MEMORY
seg000:0024 ; AL = number of sectors to read, CH = track, CL = sector
seg000:0024 ; DH = head, DL = drive, ES:BX -> buffer to fill
seg000:0024 ; Return: CF set on error, AH = status, AL = number of sectors read
seg000:0026 jnb short loc_2A
seg000:0028
seg000:0028 loc_28: ; CODE XREF: seg000:loc_28↓j
seg000:0028 jmp short loc_28
seg000:002A ; ---------------------------------------------------------------------------
seg000:002A
seg000:002A loc_2A: ; CODE XREF: seg000:0026↑j
seg000:002A cli
seg000:002B mov ax, 1000h
seg000:002E mov ds, ax
seg000:0030 assume ds:nothing
seg000:0030 xor ax, ax
seg000:0032 mov es, ax
seg000:0034 assume es:nothing
seg000:0034 mov cx, 2000h
seg000:0037 sub si, si
seg000:0039 sub di, di
seg000:003B rep movsb
seg000:003D mov ax, 7C0h
seg000:0040
seg000:0040 loc_40: ; DATA XREF: seg000:0012↑r
seg000:0040 mov ds, ax
seg000:0042 assume ds:nothing
seg000:0042 lidt fword ptr ds:6Fh
seg000:0047 lgdt fword ptr ds:75h
seg000:004C
seg000:004C loc_4C: ; DATA XREF: seg000:0024↑r
seg000:004C mov ax, 1
seg000:004F lmsw ax
seg000:0052 jmp far ptr 8:0

然后就跳转到一个神秘的鬼地方去了

程序大概是把ebx置0了,然后作为计数变量,一共循环了10h次

把一堆数送到了内存中,经高人指点,这堆数属于中断向量

(也就是VM里面的操作数,对应相应的操作)

seg000:000001FE ; ---------------------------------------------------------------------------
seg000:000001FE push ebp
seg000:000001FF stosb
seg000:00000200 mov eax, 10h
seg000:00000205 mov ds, eax
seg000:00000207 assume ds:nothing
seg000:00000207 lss esp, large ds:0B5Ch
seg000:0000020E call sub_28B
seg000:00000213 call sub_283
seg000:00000218 mov eax, 10h ; DATA XREF: sub_28B+27↓r
seg000:0000021D mov ds, eax
seg000:0000021F mov es, eax
seg000:00000221 assume es:nothing
seg000:00000221 mov fs, eax ; DATA XREF: sub_283↓r
seg000:00000223 assume fs:nothing
seg000:00000223 mov gs, eax
seg000:00000225 assume gs:nothing
seg000:00000225
seg000:00000225 loc_225: ; DATA XREF: sub_28B+11↓o
seg000:00000225 lss esp, large ds:0B5Ch
seg000:0000022C xor ebx, ebx
seg000:0000022E
seg000:0000022E loc_22E: ; CODE XREF: seg000:0000025D↓j
seg000:0000022E nop
seg000:0000022F cmp ebx, 10h
seg000:00000232 jge short loc_25F

seg000:00000234 mov eax, 80000h
seg000:00000239 lea edx, ds:0D08h[ebx*4] ;这个内存里面全部存的0
seg000:00000240 mov edx, [edx]
seg000:00000242 mov ax, dx
seg000:00000245 mov dx, 8E00h
seg000:00000249 mov ecx, 21h ; '!' ;21h
seg000:0000024E add ecx, ebx ;21h + ebx,
;也就是把21h开始的10h个数作为操作数
seg000:00000250 lea esi, ds:128h[ecx*8]
seg000:00000257 mov [esi], eax
seg000:00000259 mov [esi+4], edx
seg000:0000025C inc ebx
seg000:0000025D jmp short loc_22E
seg000:0000025F ; ---------------------------------------------------------------------------

# 后面是多次中断进行操作
seg000:0000025F
seg000:0000025F loc_25F: ; CODE XREF: seg000:00000232↑j
seg000:0000025F ; seg000:00000266↓j
seg000:0000025F call sub_268
seg000:00000264 int 21h ; DOS -
seg000:00000266 jmp short loc_25F

switch跳转语句

中断之前call的sub_268汇编代码如下:

seg000:00000268 sub_268         proc near               ; CODE XREF: seg000:loc_25F↑p
seg000:00000268 mov edi, large ds:0B78h
seg000:0000026E lea edi, ds:0D48h[edi*4]
seg000:00000275 mov eax, [edi]
seg000:00000277 mov large ds:65h, al
seg000:0000027C mov ecx, [edi+4]
seg000:0000027F mov eax, [edi+8]
seg000:00000282 retn
seg000:00000282 sub_268 endp

操作数1被送入内存了

ecx应该是操作数2

eax是操作数3

各个case

汇编

以下是每个操作数对应的操作, 因为所有的操作数是依次出现的 ,所以只需要挨着翻译就好了

seg000:00000D7C ; ---------------------------------------------------------------------------
seg000:00000D7C lea ecx, ds:0B64h[ecx*4]
seg000:00000D83 mov [ecx], eax
seg000:00000D85 jmp loc_EF8
seg000:00000D8A ; ---------------------------------------------------------------------------
seg000:00000D8A lea eax, ds:0B64h[eax*4]
seg000:00000D91 mov eax, [eax]
seg000:00000D93 lea ecx, ds:0B64h[ecx*4]
seg000:00000D9A mov [ecx], eax
seg000:00000D9C jmp loc_EF8
seg000:00000DA1 ; ---------------------------------------------------------------------------
seg000:00000DA1 lea eax, ds:0B64h[eax*4]
seg000:00000DA8 mov eax, [eax]
seg000:00000DAA lea ecx, ds:0B64h[ecx*4]
seg000:00000DB1 lea eax, ds:0D48h[eax*4]
seg000:00000DB8 mov eax, [eax]
seg000:00000DBA mov [ecx], eax
seg000:00000DBC jmp loc_EF8
seg000:00000DC1 ; ---------------------------------------------------------------------------seg000:00000DC1 lea eax, ds:0B64h[eax*4]
seg000:00000DC8 mov eax, [eax]
seg000:00000DCA lea ecx, ds:0B64h[ecx*4]
seg000:00000DD1 mov ecx, [ecx]
seg000:00000DD3 lea ecx, ds:0D48h[ecx*4]
seg000:00000DDA mov [ecx], eax
seg000:00000DDC jmp loc_EF8
seg000:00000DE1 ; ---------------------------------------------------------------------------
seg000:00000DE1 lea eax, ds:0B64h[eax*4]
seg000:00000DE8 mov edx, [eax]
seg000:00000DEA lea ecx, ds:0B64h[ecx*4]
seg000:00000DF1 mov eax, [ecx]
seg000:00000DF3 add eax, edx
seg000:00000DF5 mov [ecx], eax
seg000:00000DF7 jmp loc_EF8
seg000:00000DFC ; ---------------------------------------------------------------------------
seg000:00000DFC lea eax, ds:0B64h[eax*4]
seg000:00000E03 mov edx, [eax]
seg000:00000E05 lea ecx, ds:0B64h[ecx*4]
seg000:00000E0C mov eax, [ecx]
seg000:00000E0E sub eax, edx
seg000:00000E10 mov [ecx], eax
seg000:00000E12 jmp loc_EF8
seg000:00000E17 ; ---------------------------------------------------------------------------
seg000:00000E17 lea eax, ds:0B64h[eax*4]
seg000:00000E1E mov edx, [eax]
seg000:00000E20 lea ecx, ds:0B64h[ecx*4]
seg000:00000E27 mov eax, [ecx]
seg000:00000E29 xor eax, edx
seg000:00000E2B mov [ecx], eax
seg000:00000E2D jmp loc_EF8
seg000:00000E32 ; ---------------------------------------------------------------------------
seg000:00000E32 lea eax, ds:0B64h[eax*4]
seg000:00000E39 mov eax, [eax]
seg000:00000E3B lea edx, ds:0B64h[ecx*4]
seg000:00000E42 mov cl, al
seg000:00000E44 mov eax, [edx]
seg000:00000E46 shl eax, cl
seg000:00000E48 mov [edx], eax
seg000:00000E4A jmp loc_EF8
seg000:00000E4F ; ---------------------------------------------------------------------------
seg000:00000E4F lea eax, ds:0B64h[eax*4]
seg000:00000E56 mov eax, [eax]
seg000:00000E58 lea edx, ds:0B64h[ecx*4]
seg000:00000E5F mov cl, al
seg000:00000E61 mov eax, [edx]
seg000:00000E63 shr eax, cl
seg000:00000E65 mov [edx], eax
seg000:00000E67 jmp loc_EF8
seg000:00000E6C ; ---------------------------------------------------------------------------
seg000:00000E6C lea eax, ds:0B64h[eax*4]
seg000:00000E73 mov eax, [eax]
seg000:00000E75 lea ecx, ds:0B64h[ecx*4]
seg000:00000E7C mov edx, [ecx]
seg000:00000E7E and eax, edx
seg000:00000E80 mov [ecx], eax
seg000:00000E82 jmp short loc_EF8
seg000:00000E84 ; ---------------------------------------------------------------------------
seg000:00000E84 lea eax, ds:0B64h[ecx*4]
seg000:00000E8B mov eax, [eax]
seg000:00000E8D lea ecx, unk_B78
seg000:00000E93 mov [ecx], eax
seg000:00000E95 iret
seg000:00000E96 ; ---------------------------------------------------------------------------
seg000:00000E96 lea eax, ds:0B64h[eax*4]
seg000:00000E9D mov eax, [eax]
seg000:00000E9F test eax, eax
seg000:00000EA1 jnz short loc_EF8
seg000:00000EA3 lea eax, ds:0B64h[ecx*4]
seg000:00000EAA mov eax, [eax]
seg000:00000EAC lea ecx, unk_B78
seg000:00000EB2 mov [ecx], eax
seg000:00000EB4 iret
seg000:00000EB5 ; ---------------------------------------------------------------------------
seg000:00000EB5 lea eax, ds:0B64h[eax*4]
seg000:00000EBC mov eax, [eax]
seg000:00000EBE test eax, eax
seg000:00000EC0 jz short loc_EF8
seg000:00000EC2 lea eax, ds:0B64h[ecx*4]
seg000:00000EC9 mov eax, [eax]
seg000:00000ECB lea ecx, unk_B78
seg000:00000ED1 mov [ecx], eax
seg000:00000ED3 iret
seg000:00000ED4 ; ---------------------------------------------------------------------------
seg000:00000ED4 lea eax, unk_F94
seg000:00000EDA call sub_2EA
seg000:00000EDF hlt
seg000:00000EE0 ; ---------------------------------------------------------------------------
seg000:00000EE0 lea eax, unk_FA0
seg000:00000EE6 call sub_2EA
seg000:00000EEB lea eax, word_FAE
seg000:00000EF1 call sub_2EA
seg000:00000EF6 hlt
seg000:00000EF6 ; ---------------------------------------------------------------------------
seg000:00000EF7 db 0F4h
seg000:00000EF8 ; ---------------------------------------------------------------------------
seg000:00000EF8
seg000:00000EF8 loc_EF8: ; CODE XREF: seg000:00000D85↑j
seg000:00000EF8 ; seg000:00000D9C↑j ...
seg000:00000EF8 lea ecx, unk_B78
seg000:00000EFE mov eax, [ecx]
seg000:00000F00 add eax, 3
seg000:00000F03 mov [ecx], eax
seg000:00000F05 iret
seg000:00000F05 ; ---------------------------------------------------------------------------

翻译后

buf[a] = b
buf[a] = buf[b]
buf[a] = (dword) opt[buf[b]]
(dword) opt[buf[a]] = buf[b]
buf[a] += buf[b]
buf[a] -= buf[b]
buf[a] ^= buf[b]
buf[a] <<= buf[b]
buf[a] >>= buf[b]
buf[a] &= buf[b]
temp = buf[a]
if(buf[b] == 0) temp = buf[a]
if(buf[b] != 0) temp = buf[a]
exit(0)
printf("wrong")
printf("right")

指令数组

内存

数据区,存储操作数,这个是通过

seg000:0000026E                 lea     edi, ds:0D48h[edi*4]

算出来的

seg000:00000F48                 db  21h ; !             ; data start
seg000:00000F49 db 0
seg000:00000F4A db 0
seg000:00000F4B db 0
seg000:00000F4C db 0
seg000:00000F4D db 0
seg000:00000F4E db 0
seg000:00000F4F db 0
seg000:00000F50 db 81h
seg000:00000F51 db 0
seg000:00000F52 db 0
seg000:00000F53 db 0
seg000:00000F54 db 27h ; '
seg000:00000F55 db 0
seg000:00000F56 db 0
seg000:00000F57 db 0
seg000:00000F58 dd 2 dup(1), 24h, 2 dup(1), 23h, 2, 0
seg000:00000F78 db 22h ; "
seg000:00000F79 align 4
seg000:00000F7C db 3
seg000:00000F7D align 10h
seg000:00000F80 db 2
seg000:00000F81 align 4
seg000:00000F84 dd offset dword_0+21h
seg000:00000F88 dd 4, 8, 28h
seg000:00000F94 unk_F94 db 3 ; DATA XREF: seg000:00000ED4↑o
seg000:00000F95 align 4
seg000:00000F98 dd 4, 27h
seg000:00000FA0 unk_FA0 db 2 ; DATA XREF: seg000:00000EE0↑o
seg000:00000FA1 align 4
seg000:00000FA4 db 3
seg000:00000FA5 align 4
seg000:00000FA8 dd offset dword_0+28h
seg000:00000FAC db 3
seg000:00000FAD align 2
seg000:00000FAE word_FAE dw 0 ; DATA XREF: seg000:00000EEB↑o
seg000:00000FB0 dd 4, 27h, 2, 3, 28h, 3, 4, 27h, 2, 3, 27h, 2 dup(3), 23h
seg000:00000FB0 dd 4, 3, 24h, 3, 2, 27h, 2, 4, 24h, 0
seg000:00001010 db 2
seg000:00001011 align 4
seg000:00001014 dd offset dword_0+21h
seg000:00001018 dd 2 dup(1), 25h, 0
seg000:00001028 dd 1, 22h, 1, 0
seg000:00001038 dd offset dword_0+21h
seg000:0000103C db 2
seg000:0000103D align 10h
seg000:00001040 db 81h
seg000:00001041 align 4
seg000:00001044 dd offset dword_0+26h
seg000:00001048 dd 1, 2, 21h, 2, 9, 26h, 1, 2, 21h, 2, 9, 2Dh, 2, 1, 21h
seg000:00001048 dd 0
seg000:00001088 db 81h
seg000:00001089 align 4
seg000:0000108C db 22h ; "
seg000:0000108D align 10h
seg000:00001090 dd 1, 0
seg000:00001098 dd offset dword_0+21h
seg000:0000109C db 2
seg000:0000109D align 10h
seg000:000010A0 dd 9, 25h, 1, 2, 23h, 3, 0
seg000:000010BC db 23h ; #
seg000:000010BD align 10h
seg000:000010C0 dd 4, 1, 26h, 3, 4, 21h, 4, 7Eh, 2Dh, 4, 3, 21h, 3, 1
seg000:000010C0 dd 25h, 0
seg000:00001100 db 3
seg000:00001101 align 4
seg000:00001104 db 25h ; %
seg000:00001105 align 4
seg000:00001108 dd 1, 3, 26h, 2, 3, 21h, 4, 5Ah, 2Dh, 4, 2, 2Fh, 2 dup(0)
seg000:00001140 dd offset dword_0+30h
seg000:00001144 dd 2 dup(0)
seg000:0000114C db 38h ; 8
seg000:0000114D db 62h, 64h, 61h

dump

addr = 0x0F48
print "\nopt:"

while(1):
opt = Dword(addr)
a = Dword(addr + 4)
b = Dword(addr + 8)
print opt,",",a,",",b,",",
if(opt >= 0x2E):
break
addr += 12

翻译

妈耶,好不容易把指令翻译成了C语言,结果发现这段代码里面还嵌套了类似汇编的指令,还有循环,需要翻译

0       buf0 = 129    				//buf0 = 129
1 buf1 ^= buf1 //buf1 = 0
2 (dword) data[buf1] = buf1 //data[0] = 0
3 buf2 = (dword) data[buf0] //buf2 = data[129]
4 buf3 = buf2 //buf3 = data[129]
5 buf4 = 8 //buf4 = 8
6 buf3 <<= buf4 //buf3 = data[129] << 8
7 buf2 ^= buf3 //buf2 = data[129] ^ (data[129] << 8)
8 buf3 <<= buf4 //buf3 = data[129] << 16
9 buf2 ^= buf3
10 buf3 <<= buf4
11 buf2 ^= buf3

//buf2 = data[129] ^ (data[129] << 8) ^ (data[129] << 16) ^ (data[129] << 24)
// = afterXor

12 buf3 ^= buf3 //buf3 = 0
13 buf4 = (dword) data[buf3] //buf4 = data[0]
14 (dword) data[buf3] = buf2 //data[0] = afterXor
15 buf2 ^= buf4 //buf2 = afterXor ^ data[0]
16 (dword) data[buf0] = buf2 //data[129] = afterXor ^ data[0]
17 buf1 = 1 //buf1 = 1
18 buf0 += buf1 //buf0 = 130
19 buf1 = buf0 //buf1 = 130
20 buf2 = 129 //buf2 = 129
21 buf1 -= buf2 //buf1 = 1
22 buf2 = 9 //buf2 = 9
23 buf1 -= buf2 //buf1 = -8
24 buf2 = 9 //buf2 = 9

25 if(buf1 != 0) temp = buf2 //经高人指点,这里是设置eip
//jmp 3

26 buf0 = 129 //buf0 = 129
27 buf1 = buf0 //buf1 = 129
28 buf2 = 9 //buf2 = 9
29 buf1 += buf2 //buf1 = 138
30 buf3 = (dword) data[buf0] //buf3 = data[129]
31 buf4 = (dword) data[buf1] //buf4 = data[138]
32 buf3 -= buf4 //buf3 = data[129] - data[138]
33 buf4 = 126 //buf4 = 126

34 if(buf3 != 0) temp = buf4 //jmp 42

35 buf3 = 1 //buf3 = 1
36 buf0 += buf3 //buf0 = data[129] - data[138] + 129
37 buf1 += buf3 //buf1 = 139
38 buf2 -= buf3 //buf2 = 8
39 buf4 = 90 //buf4 = 90
40 if(buf2 != 0) temp = buf4
41 printf("wrong")
42 printf("right")

再翻译

程序作了一个很奇怪的循环,并且异或了一大堆

这个程序要逆向实在太难了,考虑到本来这个数据也不大,就暴力枚举

script from yypE:

def dec(arr):
assert(len(arr)==9)
last = 0
for i in range(9):
var = 0
arr[i] ^= last
last = arr[i]
var |= arr[i] & 0xff
for j in range(1,4):
var |= (byte(arr[i],j) ^ byte(arr[i],j-1)) <<(8*j)
arr[i] = var
return arr
def enc(arr):
assert(len(arr)==9)
last = 0
for i in range(9):
var = 0
for j in range(4):
var ^= (arr[i]<<(8*j)) & 0xffffffff
arr[i] = var ^ last
last = var
return arr

获得flag:

def gen_flag():
ar = [1466127717, 106103809, 524896585, 1364657951, 1465860951, 1464032855, 1129775626, 1465779038, 257490944]
flag = b''
for each in dec(ar):
flag+=each.to_bytes(4,'little')
print(flag)

虚拟机+反汇编+循环+暴力搜索

难点

  1. 猜出来程序的入口点
  2. 猜出修改的temp变量原来是EIP
  3. 逆向带循环的程序
  4. 耐心