能力值:
( LV4,RANK:50 )
2 楼
upx -d直接脱壳了事
能力值:
( LV2,RANK:10 )
3 楼
不懂帮顶。
能力值:
( LV2,RANK:10 )
4 楼
。。。我当然知道upx -d可以脱,但是另外那个不知道源代码的程序修改了,upx -d不可以直接脱。也是为了学习一下
能力值:
( LV12,RANK:270 )
5 楼
手脱upx根本不用管壳做了什么。init_array返回之后,直接dump内存就行了
能力值:
( LV4,RANK:50 )
6 楼
readelf -a ./test1
显示:
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x0000000000047715 0x0000000000047715 R E 200000
LOAD 0x00000000000c41a8 0x00000000006c41a8 0x00000000006c41a8
0x0000000000000000 0x0000000000000000 RW 200000
你运行test1程序后,gdb attach,附加到调试进程,然后dump出起始地址:400000,结束地址:6C5000进程内容到文件test2中。怎么DUMP,请在gdb中输入help dump命令查看。
再用readelf -a ./test2文件,可以看到:
ELF Header:
Magic: 7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - GNU
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x400f4e
Start of program headers: 64 (bytes into file)
Start of section headers: 794024 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 6
Size of section headers: 64 (bytes)
Number of section headers: 31
Section header string table index: 28
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] <no-name> NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] <no-name> NULL 0000000000000000 00000000
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x00000000000bf478 0x00000000000bf478 R E 200000
LOAD 0x00000000000bfea0 0x00000000006bfea0 0x00000000006bfea0
0x0000000000001d90 0x0000000000004308 RW 200000
NOTE 0x0000000000000190 0x0000000000400190 0x0000000000400190
0x0000000000000044 0x0000000000000044 R 4
TLS 0x00000000000bfea0 0x00000000006bfea0 0x00000000006bfea0
0x0000000000000020 0x0000000000000058 R 10
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 10
GNU_RELRO 0x00000000000bfea0 0x00000000006bfea0 0x00000000006bfea0
0x0000000000000160 0x0000000000000160 R 1
从上面信息我们可以找到正确的程式入口点 Entry point address: 0x400f4e,重新GDB载入test1,在入口点处下断点,运行,中断在入口点后,重新dump程式进程内容。
我们还需要修改:
Start of section headers: 794024 (bytes into file)
改此处值为0,程序载入器用不着这个数据。
由于我们是直接dump出连续的内存空间,所以我们还需要修改:
Program Headers:
各程序段的offset与virtaddr相符合。
修改完这两处后,就算是脱壳完成了。
UPX壳很简单,不需要修复符号信息和重定位信息。建议你在脱壳前先看看ELF格式。
能力值:
( LV2,RANK:10 )
7 楼
。。。。修改错了,应该修改的下面的回复修改到这了,,,,
能力值:
( LV2,RANK:10 )
8 楼
好的我试试,谢谢~
能力值:
( LV12,RANK:270 )
9 楼
要断在linker里面。根据实际情况。如果只有UPX的话,so加载完了再dump就行,根本不用下断点。
断linker里面就是为了防止在后续的代码里面,把一些没用的加载信息抹去,那还要修复,麻烦。
能力值:
( LV12,RANK:270 )
10 楼
卧槽~穿越了。x64的upx,还是可执行文件。之前的当我没说。
按PC的手脱呗,upx的oep特征还是很明显。
简单看了一下你的问题,第一个call是不一定有返回的,因为壳运行完了,会jmp到oep执行。
能力值:
( LV2,RANK:10 )
11 楼
你好,我刚才试了一下(下午那会后来有点事所以现在才试),
就是:运行后再attach的话,程序已经就断在真正程序的系统调用里了(因为调用了scanf),然后这时候下entry的断点没办法运行到入口点;
然后gdb直接加载test1的话是没办法start的,它提示
warning: no loadable sections found in added symbol-file /home/targetnull/Desktop/Xiao_CTF/upx-3.91-amd64_linux/test1
(no debugging symbols found)...done.
不知道你是怎么用gdb调试的呢,能否告知一下,谢谢
------------------------------------------------------
刚才又试了一下,发现因为attach的时候没法断在入口点,而是直接断在了程序中,可以直接/x20i entry来看入口的代码,但是要得到完整程序估计还是dump出来比较好。
然后请问你dump的时候结束地址怎么选取的呢,直接选取(start + size)的最大值再以4K一页对齐后的值吗?
最后就是你说要修复program header使得size和virtaddr相等,我看了下,那就是应该只有那个第二个LOAD的segment需要修改了,但是这个要追究原因的话估计和装载机制有关了吧,能否推荐一两篇相关的资料学习学习呢?网上的一些博客讲的太笼统,太原理化了。。。
能力值:
( LV2,RANK:10 )
12 楼
你好,请问你说的这个方法该如何下断点呢,用什么来调试呢?
它断的时候就是在系统调用了(程序里有scanf),这时已经过了真正入口点了,只能dump或者用x/10i这样来看了
------------------------------------------------------------
刚才试了下楼上的方法,可以得到正确入口点了,然后接下来估计就是更改header的一些数据了吧
不过还是没办法去动态跟踪到程序入口点
能力值:
( LV2,RANK:10 )
13 楼
内存dump可以参考http://bbs.pediy.com/showthread.php?t=79061,不过这个在IDA6.8下有BUG,会将0A输出为0D 0A。。也是醉了,可以自己写脚本从/proc/pid/mem中dump
使用IDA远程调试啊,IDA里断在start,然后F9启动远程调试,然后找OEP就好了啊
能力值:
( LV2,RANK:10 )
14 楼
试了下这题,最终还是要单步调到eop,dump出来才能正常跑。采臣取eop的方法是不行的。