0

I'm doing some ctf-like homework. It's to make a privileged program run /bin/sh. There's no source code, only works on binary assembly.

The program normally pass "/bin/ls %s" (stored at 0x804868f) to snprintf with argv[1]. So the output of snprintf (@main+222) would be sth like /bin/ls ~/. Then pass "/bin/ls ~/" to a system call (@main+236), like system(/bin/ls ~/).

The program filtered out some cmd line symbol by using strchr(e.g. @main+85), which are &, | and ;.

So I think you can't make the command become /bin/ls ;sh since it contains ;, for example.

My question is: Is this code seems to be unbreakable? Or how can we change the input to make the program run 'sh'.

Thanks in advance.

(also, I have no permission to modify /bin/ls)

Here's the code:

  0x08048454 <+0>: push   %ebp
  0x08048455 <+1>: mov    %esp,%ebp
  0x08048457 <+3>: sub    $0x428,%esp
  0x0804845d <+9>: and    $0xfffffff0,%esp
  0x08048460 <+12>:    mov    $0x0,%eax
  0x08048465 <+17>:    sub    %eax,%esp
  0x08048467 <+19>:    mov    0xc(%ebp),%eax
  0x0804846a <+22>:    add    $0x4,%eax
  0x0804846d <+25>:    cmpl   $0x0,(%eax)
  0x08048470 <+28>:    jne    0x8048496 <main+66>
  0x08048472 <+30>:    movl   $0x8048674,0x4(%esp)
  0x0804847a <+38>:    mov    0x80497ac,%eax
  0x0804847f <+43>:    mov    %eax,(%esp)
  0x08048482 <+46>:    call   0x8048348 <fprintf@plt>
  0x08048487 <+51>:    movl   $0xffffffff,-0x40c(%ebp)
  0x08048491 <+61>:    jmp    0x804854f <main+251>
  0x08048496 <+66>:    mov    0xc(%ebp),%eax
  0x08048499 <+69>:    add    $0x4,%eax
  0x0804849c <+72>:    movl   $0x3b,0x4(%esp)
  0x080484a4 <+80>:    mov    (%eax),%eax
  0x080484a6 <+82>:    mov    %eax,(%esp)
  0x080484a9 <+85>:    call   0x8048338 <strchr@plt>
  0x080484ae <+90>:    test   %eax,%eax
  0x080484b0 <+92>:    jne    0x80484ec <main+152>
  0x080484b2 <+94>:    mov    0xc(%ebp),%eax
  0x080484b5 <+97>:    add    $0x4,%eax
  0x080484b8 <+100>:   movl   $0x7c,0x4(%esp)
  0x080484c0 <+108>:   mov    (%eax),%eax
  0x080484c2 <+110>:   mov    %eax,(%esp)
  0x080484c5 <+113>:   call   0x8048338 <strchr@plt>
  0x080484ca <+118>:   test   %eax,%eax
  0x080484cc <+120>:   jne    0x80484ec <main+152>
  0x080484ce <+122>:   mov    0xc(%ebp),%eax
  0x080484d1 <+125>:   add    $0x4,%eax
  0x080484d4 <+128>:   movl   $0x26,0x4(%esp)
  0x080484dc <+136>:   mov    (%eax),%eax
  0x080484de <+138>:   mov    %eax,(%esp)
  0x080484e1 <+141>:   call   0x8048338 <strchr@plt>
  0x080484e6 <+146>:   test   %eax,%eax
  0x080484e8 <+148>:   jne    0x80484ec <main+152>
  0x080484ea <+150>:   jmp    0x804850d <main+185>
  0x080484ec <+152>:   movl   $0x804867c,0x4(%esp)
  0x080484f4 <+160>:   mov    0x80497ac,%eax
  0x080484f9 <+165>:   mov    %eax,(%esp)
  0x080484fc <+168>:   call   0x8048348 <fprintf@plt>
  0x08048501 <+173>:   movl   $0xffffffff,-0x40c(%ebp)
  0x0804850b <+183>:   jmp    0x804854f <main+251>
  0x0804850d <+185>:   mov    0xc(%ebp),%eax
  0x08048510 <+188>:   add    $0x4,%eax
  0x08048513 <+191>:   mov    (%eax),%eax
  0x08048515 <+193>:   mov    %eax,0xc(%esp)
  0x08048519 <+197>:   movl   $0x804868f,0x8(%esp)
  0x08048521 <+205>:   movl   $0x400,0x4(%esp)
  0x08048529 <+213>:   lea    -0x408(%ebp),%eax
  0x0804852f <+219>:   mov    %eax,(%esp)
  0x08048532 <+222>:   call   0x8048378 <snprintf@plt>
  0x08048537 <+227>:   lea    -0x408(%ebp),%eax
  0x0804853d <+233>:   mov    %eax,(%esp)
  0x08048540 <+236>:   call   0x8048358 <system@plt>
  0x08048545 <+241>:   movl   $0x0,-0x40c(%ebp)
  0x0804854f <+251>:   mov    -0x40c(%ebp),%eax
  0x08048555 <+257>:   leave  
  0x08048556 <+258>:   ret  
Joao Vitorino
  • 2,976
  • 3
  • 26
  • 55
Xarath
  • 9
  • 1
  • I don't think this is a real question: *"... is this code seems to be unbreakable?"* Or maybe, it is not a good fit at Stack Overflow. You should probably use another site on the [Stack Exchange network](https://stackexchange.com/sites) for this question. – jww Apr 03 '19 at 19:24
  • 1
    Plenty of ways. `/bin/ls\nsh` and `/bin/ls $(sh /tmp/myscript)` are a few – that other guy Apr 03 '19 at 19:25
  • @thatotherguy thanks for your reply. I tried both your comment, afraid not work:( The vulnerable program has permission -r-xr-sr-x 1 user levX, where levX is the privileged group name with 's' flag enabled (but 'user' is not one of this group). So when I run the vulnerable program, s flag could temporarily set my gid to levX then run sh. But if I use $, the program would be like run sh in cmd line, which is only under my uid and gid. And "/bin/ls\nsh" doesn't work as well, output: "/bin/ls: cannot access sh: No such file or directory". – Xarath Apr 03 '19 at 20:07
  • @Xarath `system(..)` will invoke a shell with the privileges of the current process, and that includes any `$(..)`s. You need to make sure you pass them unexpanded though. As for `/bin/ls\nsh`, you are somehow instead running `/bin/ls sh`. I don't know if this is because the program filters `\n` in addition to the list you provided, or because the linefeed got mangled by your invocation or something else. Please give the exact commands you use to test. – that other guy Apr 03 '19 at 20:20
  • Try: `/bin/ls $(exec /bin/sh)`. This worked for me on a network router. – user253751 Apr 03 '19 at 20:52
  • @thatotherguy I use `./program \`perl -e 'print "\nsh"'\``, and also tried `./program \\nsh`, `./program \nsh` – Xarath Apr 03 '19 at 23:00
  • @Xarath That won't work because the lack of quotes is causing the linefeed to be stripped. You can use ``./program "`perl -e 'print "\nsh"'`"`` or more directly `./program $'\nsh'` in bash (but not in dash), or alternatively, write `./program 'foo`, then press enter on the prompt to insert a literal linefeed and continue the command on the next line, then `sh'` – that other guy Apr 03 '19 at 23:04
  • @thatotherguy ohhhhh yeas! man, thank you so much!! – Xarath Apr 04 '19 at 00:19

0 Answers0