首页 > 代码库 > iOS可执行文件的简单反ida

iOS可执行文件的简单反ida

ida就不用我就废话了,这篇主要讲解如何通过对mach-o文件简单的更改达到反ida静态分析的目的。

先说一下mach-o文件格式的节。

?

?

  1. struct?section?{?/*?for?32-bit?architectures?*/??
  2. ????char????????sectname[16];???/*?name?of?this?section?*/??
  3. ????char????????segname[16];????/*?segment?this?section?goes?in?*/??
  4. ????uint32_t????addr;???????/*?memory?address?of?this?section?*/??
  5. ????uint32_t????size;???????/*?size?in?bytes?of?this?section?*/??
  6. ????uint32_t????offset;?????/*?file?offset?of?this?section?*/??
  7. ????uint32_t????align;??????/*?section?alignment?(power?of?2)?*/??
  8. ????uint32_t????reloff;?????/*?file?offset?of?relocation?entries?*/??
  9. ????uint32_t????nreloc;?????/*?number?of?relocation?entries?*/??
  10. ????uint32_t????flags;??????/*?flags?(section?type?and?attributes)*/??
  11. ????uint32_t????reserved1;??/*?reserved?(for?offset?or?index)?*/??
  12. ????uint32_t????reserved2;??/*?reserved?(for?count?or?sizeof)?*/??
  13. }; ?

属性的主要作用是告诉加载,本节要加载到内存的虚拟地址(addr),大小(size),及节在文件物理地址的偏移(offset)。

实际上mach-o文件格式详细的指导了加载器如何加载文件到内存,但是ios并没有完全按照格式来加载,可执行文件合法性的验证只是做到了segment一层,对于节section一层并没有验证,加载器只是简单的将段地址线性的映射到内存,粒度很大,没有细化到节,所以节属性在加载的时候没有用,但是ida是个好学生,完全依靠mach格式来分析文件,bug就出现了。(实际上在win下,od也有类似的bug),那么下面我们来手动更改文件,达到ida不能加载,ios却能正常运行的效果。

实验1:更改节的物理地址偏移。

1,首先将文件拖到ida,我们看到TEXT段下面的2个节。

“__text"与"__stub_helper"

HEADER:0000408C DCB "__text",0,0,0,0,0,0,0,0,0,0; sectname

HEADER:0000408C DCB "__TEXT",0,0,0,0,0,0,0,0,0,0; segname

HEADER:0000408C DCD 0xAD00 ; addr

HEADER:0000408C DCD 0xD6938 ; size

HEADER:0000408C DCD 0x6D00 ; offset

HEADER:0000408C DCD 3 ; align

HEADER:0000408C DCD 0 ; reloff

HEADER:0000408C DCD 0 ; nreloc

HEADER:0000408C DCD 0x80000400 ; flags

HEADER:0000408C DCD 0 ; reserved1

HEADER:0000408C DCD 0 ; reserved2

HEADER:000040D0 DCB "__stub_helper",0,0,0; sectname

HEADER:000040D0 DCB "__TEXT",0,0,0,0,0,0,0,0,0,0; segname

HEADER:000040D0 DCD 0xE1638 ; addr

HEADER:000040D0 DCD 0xE88 ; size

HEADER:000040D0 DCD 0xDD638 ; offset

HEADER:000040D0 DCD 2 ; align

HEADER:000040D0 DCD 0 ; reloff

HEADER:000040D0 DCD 0 ; nreloc

HEADER:000040D0 DCD 0x80000400 ; flags

HEADER:000040D0 DCD 0 ; reserved1

HEADER:000040D0 DCD 0 ; reserved2

?

“__text”节的的内存加载地址为 0xad00,文件偏移为0x6d00

"__stub_helper"节的的内存加载地址为 0xE1638,文件偏移为0xDD638

2,我们将“__text”的的文件偏移更改为"__stub_helper"的文件偏移,修改后保持文件,继续拖到ida下分析,如下图:

?

HEADER:0000408C DCB "__text",0,0,0,0,0,0,0,0,0,0; sectname

HEADER:0000408C DCB "__TEXT",0,0,0,0,0,0,0,0,0,0; segname

HEADER:0000408C DCD 0xAD00 ; addr

HEADER:0000408C DCD 0xD6938 ; size

HEADER:0000408C DCD 0xDD638 ; offset

HEADER:0000408C DCD 3 ; align

HEADER:0000408C DCD 0 ; reloff

HEADER:0000408C DCD 0 ; nreloc

HEADER:0000408C DCD 0x80000400 ; flags

HEADER:0000408C DCD 0 ; reserved1

HEADER:0000408C DCD 0 ; reserved2

HEADER:000040D0 DCB "__stub_helper",0,0,0; sectname

HEADER:000040D0 DCB "__TEXT",0,0,0,0,0,0,0,0,0,0; segname

HEADER:000040D0 DCD 0xE1638 ; addr

HEADER:000040D0 DCD 0xE88 ; size

HEADER:000040D0 DCD 0xDD638 ; offset

HEADER:000040D0 DCD 2 ; align

HEADER:000040D0 DCD 0 ; reloff

HEADER:000040D0 DCD 0 ; nreloc

HEADER:000040D0 DCD 0x80000400 ; flags

HEADER:000040D0 DCD 0 ; reserved1

HEADER:000040D0 DCD 0 ; reserved2

?

两个节的物理偏移都为0xDD638。

双击“__text”节,进入代码的。如图:

NewImage

可以看到左下角,物理地址为0xdd638,实际上这是错误的,物理地址应该为0x6D00。我们可以得出结论,ida直接使用了节的物理地址,偷懒了,实际上应该使用段地址来计算。


实验2:给节的物理偏移更改为一个远超文件大小的数。


HEADER:0000408C ; Sections

HEADER:0000408C DCB "__text",0,0,0,0,0,0,0,0,0,0; sectname

HEADER:0000408C DCB "__TEXT",0,0,0,0,0,0,0,0,0,0; segname

HEADER:0000408C DCD 0xAD00 ; addr

HEADER:0000408C DCD 0xD6938 ; size

HEADER:0000408C DCD 0xFFFFFFFF ; offset

HEADER:0000408C DCD 3 ; align

HEADER:0000408C DCD 0 ; reloff

HEADER:0000408C DCD 0 ; nreloc

HEADER:0000408C DCD 0x80000400 ; flags

HEADER:0000408C DCD 0 ; reserved1

HEADER:0000408C DCD 0 ; reserved2

?

更改后保存文件,拖到ida,如图:



iOS可执行文件的简单反ida