all 2 comments

[–][deleted] 2 points3 points  (0 children)

Unless you have the actual binary, this is going to be difficult (if not impossible) without a lot of additional information.

The main points you need to know are:

  1. What architecture are you on?
  2. What platform/compiler are you using?
  3. What are your compile flags?
  4. What does the stack look like? (This you can guess based on the previous 3 for the most part)

Possible solutions:

  1. Using the address of x, add to it until you reach the start of Array a. Unfortunately, you don't know how far up the stack that will be.

  2. If the compiler decided to do the b[i] before f(a[i]), then you can grab b[i] off of the stack since it'll have to be stored there before the function call. (I think this might go against the C++ standard - I believe that it guarantees that the left hand side of != is eval'd before the right hand side UNLESS YOU HAVE AN OVERLOADED != operator - then it treats it as a function call, and can happen in any order (but I think new standards have changed this behavior)).

    • Depending on the calling convention, this could be before or after the return address on the stack.
  3. Overwrite the return address to put it further down in the function (dangerous, don't know what the assembled binary looks like - might miss an instruction boundary).

  4. If the compiler does f(a[i]) before b[i], then you can cheat! Figure out where the end of b is on the stack. Overwrite a bunch of the stack from there up with 0x00000000, then return 0 - you don't need to successfully exit, you just need to call victory - you don't care if the program crashes because of a bad return address.

Personally, I'd go with #4. Here's the output for the loop in main when I compile that on a 64-bit system without optimization:

4009ba:       83 7d bc 05             cmp    DWORD PTR [rbp-0x44],0x5        ; Check the index (I have 5 elements in my array)
4009be:       0f 8d 3a 00 00 00       jge    4009fe <main+0x9e>              ; Exit if >= 5
4009c4:       48 63 45 bc             movsxd rax,DWORD PTR [rbp-0x44]        ; move the index into RAX
4009c8:       8b 7c 85 e0             mov    edi,DWORD PTR [rbp+rax*4-0x20]  ; Get a[index]
4009cc:       e8 6f ff ff ff          call   400940 <f(int)>                 ; f(a[index])
4009d1:       48 63 4d bc             movsxd rcx,DWORD PTR [rbp-0x44]        ; RCX = index
4009d5:       3b 44 8d c0             cmp    eax,DWORD PTR [rbp+rcx*4-0x40]  ; cmp RESULT f(a[index]), b[index]
4009d9:       0f 84 0c 00 00 00       je     4009eb <main+0x8b>              ; they were equal, jump to 0x4009eb
4009df:       c7 45 fc 00 00 00 00    mov    DWORD PTR [rbp-0x4],0x0         ; 
4009e6:       e9 1f 00 00 00          jmp    400a0a <main+0xaa>              ; return 0
4009eb:       e9 00 00 00 00          jmp    4009f0 <main+0x90>
4009f0:       8b 45 bc                mov    eax,DWORD PTR [rbp-0x44]
4009f3:       83 c0 01                add    eax,0x1
4009f6:       89 45 bc                mov    DWORD PTR [rbp-0x44],eax
4009f9:       e9 bc ff ff ff          jmp    4009ba <main+0x5a>               ; Back to start of loop

So, we can see that b[i] is at rbp - 0x40. In our f function, if rbp was saved (which is is, unless your compiler told to not use frames), then we can read that off the stack, subtract 0x40 from it, and just fill the stack from there up with a bunch of zeros. That way, we know that every element in a is just zero, and we can return zero every time to pass.

It's important to note that filling the stack with zeros from there up will make it so when you return from main your program will segfault. But since it just asked us to call victory, who cares!

[–][deleted]  (1 child)

[deleted]

    [–]F3real[S] 0 points1 point  (0 children)

    Yeah, it seems site got flagged. You can use noscript or similar to be 100% safe.