Understanding programmers for microcontrollers
There is no magic sauce, it's all just clocks and data lines going up and down in voltage in the right succession. Sometimes the programming voltages are a bit higher than the normal interface voltages, but that's not hard to reproduce. As you noticed, your arduino can do that too, if you know how the protocol works. And that's where the problem lies.

On one hand the more complex the microcontroller is, the more complex the protocol to program it will be. You will have modes to initialize different forms of memories, set configuration parameters that control fundamental behaviour of the controller (e.g. Atmel "Fuses" which can shut off SPI or disable the internal clock source oscillator). The protocol how to do this is very low level and usually not of interest to the developer who wants to use the controller for his own product. So naturally it is the creator of the microcontroller providing an abstraction layer between controller and PC, which makes it easier to program the controller.

The other aspect is monopoly in order to profit from selling the hardware and software needed to program a certain controller. Most companies aren't interested in making it easy to program their devices with third-party or DIY programmers. Not because they're evil, but simply because it's their price policy to make the controller cheap but the periphery necessary to develop with it expensive, which results in less per-device cost. So some companies might even go the extra mile and add security mechanisms and tamper-proof protocols. A simple example would be a secret key generation algorithm and a key verification algorithm, on the programmer and the controller, respectively. When the programming begins, they perform a handshake with challenge-response-authentication. So even if you sniff the protocol and replay the exact bits on the lines, it won't work because the controller will randomly provide a different challenge at the handshake, and your parrot-programmer will produce a wrong response, telling the controller that it's not talking to the original programmer.